我正在使用 Swing 制作 UI,并制作了一个
JPopupMenu
添加到顶部栏的 JMenu
,但 paintComponent()
函数从未被调用。我在网上看到我不能有0,0
的大小,这是默认的,当我更改它时仍然没有调用paintComponent。我正在使用java 17
。
public class PopUpMenu extends JPopupMenu {
public PopUpMenu() {
setBackground(UI.tertiaryColor);
setForeground(UI.tertiaryColor);
}
@Override
protected void paintComponent(Graphics g) {
System.out.println("painting");
super.paintComponent(g);
g.setColor(UI.tertiaryColor);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(UI.tertiaryColor);
g2.fillRect(0, 0, (int) getPreferredSize().getWidth(), (int) getPreferredSize().getHeight());
}
}
public class Menu extends JMenu {
Color highlite = new Color(0x3e90ff);
int xOffSetText = 5;
public Menu(String text) {
super(text);
init();
}
public Menu(String text, int xOffSetText) {
super(text);
this.xOffSetText = xOffSetText;
init();
}
private void init() {
setFont(UI.getFont(16));
setBackground(UI.mainColor);
setForeground(UI.textColor);
setPreferredSize(new Dimension((int) getPreferredSize().getWidth(), 25));
setContentAreaFilled(false);
setBorderPainted(false);
setSelected(false);
PopUpMenu popUpMenu = new PopUpMenu();
setComponentPopupMenu(popUpMenu);
}
@Override
protected void paintComponent(Graphics g) {
g.setColor(UI.mainColor);
Graphics2D g2 = (Graphics2D) g;
if (getModel().isSelected()) {
g2.setColor(highlite);
} else {
g2.setColor(UI.mainColor);
}
g2.fillRect(0, 0, getWidth(), getHeight());
if (getModel().isSelected()) {
g2.setColor(UI.mainColor);
} else {
g2.setColor(UI.textColor);
}
g2.drawString(getText(), xOffSetText, 20);
}
}
编辑:我将
popupMenu
中与 JMenu
相关的所有功能实现到我自己的 Menu
类中。它确实调用了 paintComponent
函数,但不绘制任何东西。这些是我的新课程:
package org.example.uiComponents;
import org.example.UI;
import javax.swing.*;
import java.awt.*;
public class PopUpMenu extends JPopupMenu {
public PopUpMenu() {
setBackground(Color.white);
setForeground(Color.white);
System.out.println("popup");
}
@Override
protected void paintComponent(Graphics g) {
System.out.println("painting123....");
g.setColor(UI.tertiaryColor);
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(UI.tertiaryColor);
g2.fillRect((int) getAlignmentX(), (int) getAlignmentY(), (int) getPreferredSize().getWidth(), (int) getPreferredSize().getHeight());
}
}
public class Menu extends JMenu {
Color highlite = new Color(0x3e90ff);
int xOffSetText = 5;
PopUpMenu popupMenu = null;
public Menu(String text) {
super(text);
init();
}
public Menu(String text, int xOffSetText) {
super(text);
this.xOffSetText = xOffSetText;
init();
}
private void init() {
setFont(UI.getFont(16));
setBackground(UI.mainColor);
setForeground(UI.textColor);
setPreferredSize(new Dimension((int) getPreferredSize().getWidth(), 25));
setContentAreaFilled(false);
setBorderPainted(false);
setSelected(false);
PopUpMenu popUpMenu = new PopUpMenu();
//setComponentPopupMenu(popUpMenu);
}
private void ensurePopupMenuCreated() {
if (popupMenu == null) {
this.popupMenu = new PopUpMenu();
popupMenu.setInvoker(this);
popupListener = createWinListener(popupMenu);
}
}
@Override
public void updateUI() {
setUI((MenuItemUI)UIManager.getUI(this));
if ( popupMenu != null )
{
popupMenu.setUI((PopupMenuUI)UIManager.getUI(popupMenu));
}
}
/**
* Returns true if the menu's popup window is visible.
*
* @return true if the menu is visible, else false
*/
@Override
public boolean isPopupMenuVisible() {
ensurePopupMenuCreated();
return popupMenu.isVisible();
}
/**
* The window-closing listener for the popup.
*
* @see JMenu.WinListener
*/
protected JMenu.WinListener popupListener;
/**
* Sets the location of the popup component.
*
* @param x the x coordinate of the popup's new position
* @param y the y coordinate of the popup's new position
*/
@Override
public void setMenuLocation(int x, int y) {
setMenuLocation(x, y);
if (popupMenu != null)
popupMenu.setLocation(x, y);
}
/**
* Appends a menu item to the end of this menu.
* Returns the menu item added.
*
* @param menuItem the <code>JMenuitem</code> to be added
* @return the <code>JMenuItem</code> added
*/
@Override
public JMenuItem add(JMenuItem menuItem) {
ensurePopupMenuCreated();
return popupMenu.add(menuItem);
}
/**
* Appends a component to the end of this menu.
* Returns the component added.
*
* @param c the <code>Component</code> to add
* @return the <code>Component</code> added
*/
@Override
public Component add(Component c) {
ensurePopupMenuCreated();
popupMenu.add(c);
return c;
}
/**
* Adds the specified component to this container at the given
* position. If <code>index</code> equals -1, the component will
* be appended to the end.
* @param c the <code>Component</code> to add
* @param index the position at which to insert the component
* @return the <code>Component</code> added
* @see #remove
* @see java.awt.Container#add(Component, int)
*/
@Override
public Component add(Component c, int index) {
ensurePopupMenuCreated();
popupMenu.add(c, index);
return c;
}
/**
* Appends a new separator to the end of the menu.
*/
@Override
public void addSeparator()
{
ensurePopupMenuCreated();
popupMenu.addSeparator();
}
/**
* Inserts a new menu item with the specified text at a
* given position.
*
* @param s the text for the menu item to add
* @param pos an integer specifying the position at which to add the
* new menu item
* @exception IllegalArgumentException when the value of
* <code>pos</code> < 0
*/
@Override
public void insert(String s, int pos) {
if (pos < 0) {
throw new IllegalArgumentException("index less than zero.");
}
ensurePopupMenuCreated();
popupMenu.insert(new JMenuItem(s), pos);
}
/**
* Inserts the specified <code>JMenuitem</code> at a given position.
*
* @param mi the <code>JMenuitem</code> to add
* @param pos an integer specifying the position at which to add the
* new <code>JMenuitem</code>
* @return the new menu item
* @exception IllegalArgumentException if the value of
* <code>pos</code> < 0
*/
@Override
public JMenuItem insert(JMenuItem mi, int pos) {
if (pos < 0) {
throw new IllegalArgumentException("index less than zero.");
}
ensurePopupMenuCreated();
popupMenu.insert(mi, pos);
return mi;
}
/**
* Inserts a new menu item attached to the specified <code>Action</code>
* object at a given position.
*
* @param a the <code>Action</code> object for the menu item to add
* @param pos an integer specifying the position at which to add the
* new menu item
* @return the new menu item
* @exception IllegalArgumentException if the value of
* <code>pos</code> < 0
*/
@Override
public JMenuItem insert(Action a, int pos) {
if (pos < 0) {
throw new IllegalArgumentException("index less than zero.");
}
ensurePopupMenuCreated();
JMenuItem mi = new JMenuItem(a);
mi.setHorizontalTextPosition(JButton.TRAILING);
mi.setVerticalTextPosition(JButton.CENTER);
popupMenu.insert(mi, pos);
return mi;
}
/**
* Inserts a separator at the specified position.
*
* @param index an integer specifying the position at which to
* insert the menu separator
* @exception IllegalArgumentException if the value of
* <code>index</code> < 0
*/
@Override
public void insertSeparator(int index) {
if (index < 0) {
throw new IllegalArgumentException("index less than zero.");
}
ensurePopupMenuCreated();
popupMenu.insert( new JPopupMenu.Separator(), index );
}
/**
* Removes the specified menu item from this menu. If there is no
* popup menu, this method will have no effect.
*
* @param item the <code>JMenuItem</code> to be removed from the menu
*/
@Override
public void remove(JMenuItem item) {
if (popupMenu != null)
popupMenu.remove(item);
}
/**
* Removes the menu item at the specified index from this menu.
*
* @param pos the position of the item to be removed
* @exception IllegalArgumentException if the value of
* <code>pos</code> < 0, or if <code>pos</code>
* is greater than the number of menu items
*/
@Override
public void remove(int pos) {
if (pos < 0) {
throw new IllegalArgumentException("index less than zero.");
}
if (pos > getItemCount()) {
throw new IllegalArgumentException("index greater than the number of items.");
}
if (popupMenu != null)
popupMenu.remove(pos);
}
/**
* Removes the component <code>c</code> from this menu.
*
* @param c the component to be removed
*/
@Override
public void remove(Component c) {
if (popupMenu != null)
popupMenu.remove(c);
}
/**
* Removes all menu items from this menu.
*/
@Override
public void removeAll() {
if (popupMenu != null)
popupMenu.removeAll();
}
/**
* Returns the number of components on the menu.
*
* @return an integer containing the number of components on the menu
*/
@Override
@BeanProperty(bound = false)
public int getMenuComponentCount() {
int componentCount = 0;
if (popupMenu != null)
componentCount = popupMenu.getComponentCount();
return componentCount;
}
/**
* Returns the component at position <code>n</code>.
*
* @param n the position of the component to be returned
* @return the component requested, or <code>null</code>
* if there is no popup menu
*
*/
@Override
public Component getMenuComponent(int n) {
if (popupMenu != null)
return popupMenu.getComponent(n);
return null;
}
/**
* Returns an array of <code>Component</code>s of the menu's
* subcomponents. Note that this returns all <code>Component</code>s
* in the popup menu, including separators.
*
* @return an array of <code>Component</code>s or an empty array
* if there is no popup menu
*/
@Override
@BeanProperty(bound = false)
public Component[] getMenuComponents() {
if (popupMenu != null)
return popupMenu.getComponents();
return new Component[0];
}
/**
* A listener class that watches for a popup window closing.
* When the popup is closing, the listener deselects the menu.
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is
* appropriate for short term storage or RMI between applications running
* the same version of Swing. As of 1.4, support for long term storage
* of all JavaBeans
* has been added to the <code>java.beans</code> package.
* Please see {@link java.beans.XMLEncoder}.
*/
@SuppressWarnings("serial")
protected class WinListener extends WindowAdapter implements Serializable {
JPopupMenu popupMenu;
/**
* Create the window listener for the specified popup.
*
* @param p the popup menu for which to create a listener
* @since 1.4
*/
public WinListener(JPopupMenu p) {
this.popupMenu = p;
}
/**
* Deselect the menu when the popup is closed from outside.
*/
public void windowClosing(WindowEvent e) {
setSelected(false);
}
}
/**
* Returns an array of <code>MenuElement</code>s containing the submenu
* for this menu component. If popup menu is <code>null</code> returns
* an empty array. This method is required to conform to the
* <code>MenuElement</code> interface. Note that since
* <code>JSeparator</code>s do not conform to the <code>MenuElement</code>
* interface, this array will only contain <code>JMenuItem</code>s.
*
* @return an array of <code>MenuElement</code> objects
*/
@Override
@BeanProperty(bound = false)
public MenuElement[] getSubElements() {
if(popupMenu == null)
return new MenuElement[0];
else {
MenuElement[] result = new MenuElement[1];
result[0] = popupMenu;
return result;
}
}
/**
* Sets the <code>ComponentOrientation</code> property of this menu
* and all components contained within it. This includes all
* components returned by {@link #getMenuComponents getMenuComponents}.
*
* @param o the new component orientation of this menu and
* the components contained within it.
* @exception NullPointerException if <code>orientation</code> is null.
* @see java.awt.Component#setComponentOrientation
* @see java.awt.Component#getComponentOrientation
* @since 1.4
*/
@Override
public void applyComponentOrientation(ComponentOrientation o) {
super.applyComponentOrientation(o);
if ( popupMenu != null ) {
int ncomponents = getMenuComponentCount();
for (int i = 0 ; i < ncomponents ; ++i) {
getMenuComponent(i).applyComponentOrientation(o);
}
popupMenu.setComponentOrientation(o);
}
}
/**
* Sets the orientation for this menu and its associated popup menu
* determined by the {@code ComponentOrientation} argument.
*
* @param o the new orientation for this menu and
* its associated popup menu.
*/
@Override
public void setComponentOrientation(ComponentOrientation o) {
super.setComponentOrientation(o);
if ( popupMenu != null ) {
popupMenu.setComponentOrientation(o);
}
}
@Override
public JPopupMenu getPopupMenu() {
ensurePopupMenuCreated();
return popupMenu;
}
@Override
protected void paintComponent(Graphics g) {
g.setColor(UI.mainColor);
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (getModel().isSelected()) {
g2.setColor(highlite);
} else {
g2.setColor(UI.mainColor);
}
g2.fillRect(0, 0, getWidth(), getHeight());
if (getModel().isSelected()) {
g2.setColor(UI.mainColor);
} else {
g2.setColor(UI.textColor);
}
g2.drawString(getText(), xOffSetText, 20);
}
}
我对 MenuItems 使用了一种奇怪的解决方法