Java - setSelectedIcon() и setPressedIcon() не регистрируются
У меня есть JPopupMenu на JTree с JCheckboxMenuItem, где я хотел бы использовать пользовательские значки (Windows L&F). Я могу использовать setIcon() на JCheckboxMenuItem успешно, но по какой-то причине setSelectedIcon() и setPressedIcon() не работают.
Код ниже завершен и скомпилируется без ошибок. Однако это просто не работает. Я подтвердил, что изображения загружаются правильно, установив их через setIcon() и увидев их там.
Проводя некоторые исследования, я заметил этот вопрос, поэтому я попытался применить обходной путь, используя его, но, похоже, он не работает с использованием JPopupMenu. Я пытаюсь найти возможный обходной путь с JPopupMenu, но у меня проблемы. Я думал о добавлении MouseListener, но я хочу, чтобы он также реагировал на события клавиатуры... К сожалению, Menulistener не работает на JPopupMenu.
Вот скомпилированный, безошибочный код:
package mypackage;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.AbstractButton;
import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
public class test extends JFrame {
public static final ImageIcon icon_properties = new ImageIcon(mypackage.class.getResource("options.png"));
public static final ImageIcon icon_checked = new ImageIcon(mypackage.class.getResource("checkbox_checked.png"));
public static final ImageIcon icon_unchecked = new ImageIcon(mypackage.class.getResource("checkbox_unchecked.png"));
public static final ImageIcon icon_pressed = new ImageIcon(mypackage.class.getResource("checkbox_pressed.png"));
String SINGLE_LEFT = "single left click";
String SINGLE_MIDDLE = "single middle click";
String SINGLE_RIGHT = "single right click";
String DOUBLE_LEFT = "double left click";
String DOUBLE_MIDDLE = "double middle click";
String DOUBLE_RIGHT = "double right click";
String MENU_VISIBLE = "Visible";
String MENU_SELECTABLE = "Selectable";
String MENU_DRAGGABLE = "Draggable";
String MENU_PROPERTIES = "Properties";
protected JTree theTree;
protected DefaultMutableTreeNode theModel;
ContextMenu menu = new ContextMenu();
public test() {
setSize(400, 300);
theModel = new DefaultMutableTreeNode("LayerList") {
{
String NODE_NAME = " this is an item to select ";
DefaultMutableTreeNode node_icon = new DefaultMutableTreeNode(new DefaultMutableTreeNode(NODE_NAME));
add(node_icon);
node_icon = new DefaultMutableTreeNode(new DefaultMutableTreeNode(NODE_NAME));
add(node_icon);
node_icon = new DefaultMutableTreeNode(new DefaultMutableTreeNode(NODE_NAME));
add(node_icon);
node_icon = new DefaultMutableTreeNode(new DefaultMutableTreeNode(NODE_NAME));
add(node_icon);
node_icon = new DefaultMutableTreeNode(new DefaultMutableTreeNode(NODE_NAME));
add(node_icon);
node_icon = new DefaultMutableTreeNode(new DefaultMutableTreeNode(NODE_NAME));
add(node_icon);
node_icon = new DefaultMutableTreeNode(new DefaultMutableTreeNode(NODE_NAME));
add(node_icon);
}
};
theTree = new JTree(theModel);
theTree.putClientProperty("JTree.lineStyle", "Angled");
theTree.setRootVisible(false);
theTree.setShowsRootHandles(true);
theTree.setEditable(false);
MouseListener ml = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
int selRow = theTree.getRowForLocation(e.getX(), e.getY());
TreePath selPath = theTree.getPathForLocation(e.getX(), e.getY());
if(selRow != -1) {
if( SwingUtilities.isLeftMouseButton(e) ) {
if(e.getClickCount() == 1) {
ContextMenuClickHander(SINGLE_LEFT, selRow, selPath, e);
}
else if(e.getClickCount() >= 2) {
ContextMenuClickHander(DOUBLE_LEFT, selRow, selPath, e);
}
}
else if( SwingUtilities.isMiddleMouseButton(e) ) {
if(e.getClickCount() == 1) {
ContextMenuClickHander(SINGLE_MIDDLE, selRow, selPath, e);
}
else if(e.getClickCount() >= 2) {
ContextMenuClickHander(DOUBLE_MIDDLE, selRow, selPath, e);
}
}
else if( SwingUtilities.isRightMouseButton(e) ) {
if(e.getClickCount() == 1) {
ContextMenuClickHander(SINGLE_RIGHT, selRow, selPath, e);
}
else if(e.getClickCount() >= 2) {
ContextMenuClickHander(DOUBLE_RIGHT, selRow, selPath, e);
}
}
}
}
};
theTree.addMouseListener(ml);
JScrollPane s = new JScrollPane();
s.getViewport().add(theTree);
getContentPane().add(s, BorderLayout.CENTER);
addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } });
setVisible(true);
}
class ContextMenu extends JPopupMenu implements ActionListener {
JCheckBoxMenuItem item;
public ContextMenu(){
item = new JCheckBoxMenuItem(MENU_VISIBLE);
item.setIcon(icon_unchecked);
item.setSelectedIcon(icon_checked);
item.setPressedIcon(icon_pressed);
//item.setRolloverIcon(icon_checked);
//item.setRolloverSelectedIcon(icon_checked);
//item.setDisabledIcon(icon_checked);
//item.setDisabledSelectedIcon(icon_checked);
item.setActionCommand(MENU_VISIBLE);
item.addActionListener(this);
add(item);
item = new JCheckBoxMenuItem(MENU_SELECTABLE);
item.setIcon(icon_unchecked);
item.setSelectedIcon(icon_checked);
item.setPressedIcon(icon_pressed);
item.setActionCommand(MENU_SELECTABLE);
item.addActionListener(this);
add(item);
item = new JCheckBoxMenuItem(MENU_DRAGGABLE);
item.setIcon(icon_unchecked);
item.setSelectedIcon(icon_checked);
item.setPressedIcon(icon_pressed);
item.setActionCommand(MENU_DRAGGABLE);
item.addActionListener(this);
add(item);
JMenuItem item = new JMenuItem(MENU_PROPERTIES+"...");
item.setIcon(icon_properties);
item.setActionCommand(MENU_PROPERTIES);
item.addActionListener(this);
add(item);
}
public void actionPerformed(ActionEvent e) {
if (MENU_VISIBLE.equals(e.getActionCommand())) {
System.out.println("Clicked "+MENU_VISIBLE);
ChangeIcon(e);
}
else if (MENU_SELECTABLE.equals(e.getActionCommand())) {
System.out.println("Clicked "+MENU_SELECTABLE);
ChangeIcon(e);
}
else if (MENU_DRAGGABLE.equals(e.getActionCommand())) {
System.out.println("Clicked "+MENU_DRAGGABLE);
ChangeIcon(e);
}
else if (MENU_PROPERTIES.equals(e.getActionCommand())) {
System.out.println("Clicked "+MENU_PROPERTIES);
}
}
}
public void ChangeIcon(ActionEvent e) {
if (e.getSource() instanceof AbstractButton) {
boolean selected = ((AbstractButton) e.getSource()).isSelected();
if( selected ) {
((AbstractButton) e.getSource()).setIcon(icon_checked);
}
else {
((AbstractButton) e.getSource()).setIcon(icon_unchecked);
}
}
}
void ContextMenuClickHander(String clickType, int row, TreePath tpath, MouseEvent e) {
theTree.setSelectionPath(tpath);
System.out.println(clickType+": row="+row+", treepath="+tpath);
if( clickType.equals(SINGLE_RIGHT) ) {
menu.show(e.getComponent(), e.getX(), e.getY());
}
}
public static void main(String argv[]) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
new test().setLocationRelativeTo(null);
}
}
Вот изображения, которые я пытаюсь использовать, если это поможет:
- проверено: https://i.imgur.com/xdsSXVe.png
- не проверено: https://i.imgur.com/mFP5T9y.png
- нажал: https://i.imgur.com/Bt3jliz.png
Обновить:
Не совсем идеальный обходной путь, который я разработал, заключается в том, чтобы вручную устанавливать значок при каждом обнаружении щелчка. В функции "actionPerformed(ActionEvent e)" после каждого оператора println добавьте новую строку с "ChangeIcon(e);", а когда это будет сделано, просто добавьте эту функцию:
Тем не менее, кажется, что Windows L & F все еще добавляет свою собственную наведенную / выбранную границу (см. Изображение) Я надеюсь, что у кого-то еще есть реальное решение...
Обновление 2:
Обновлен полный код с первым кодом обновления, немного подправлен пост.