Java阻止JComponent的焦点

我为我的申请做了一个gui。 JFrame有2个JPanel,panel1和panel2。 panel1就是这样,一个带有自定义绘画的JPanel,每5毫秒重绘一次。

panel2是我第一次尝试CardLayout:它包含JPanels subPanel1和subPanel2。 subPanel1包含一个JComboBox并添加到panel2: panel2.add(subPanel1);

subPanel2有.setLayout(new CardLayout()); 命令,我添加3个新的JPanels,适当的itemListener和所有。 当然我也添加它: panel2.add(subPanel2);

现在问题是:在Java中集中组件。 我知道方法setFocusable(boolean)requestFocus() 。 但我不能让它们以任何合乎逻辑的方式行事。

首先,它们的根本问题是:当combobox获得焦点时,我根本无法完全聚焦它(尝试用光标点击到处)。

以下是我进行的实验:

1)没有任何代码在整个应用程序中进行聚焦,无论将哪个命令面板1和面板2添加到JFrame,combobox都从焦点开始。

2)如果我设置了panel1.setFocusable(true); (在它的构造函数中)它将从焦点开始

3)如果我设置了panel1.setFocusable(false); 并要求专注于它,它没有得到它。 (只有按预期工作的东西)

4)如果我将panel2,subPanel1或subPanel2设置为单独或以任何组合不可聚焦,它们仍然可以获得焦点(combobox,即,这是唯一能够注册焦点的组件)。

5)如果我将combobox设置为不可聚焦,我仍然可以使用框’itemListener在CardLayout中的卡之间滚动,但焦点不会粘在它上面。 事实上,panel1仍然记录键盘输入

所以我真的很担心整个’焦点’的事情。 也许这不是我认为的那样? 我想要做的是完全阻止与panel2的所有交互,直到一个标志(每5毫秒评估一次)为真。 我是否正确假设与JPanel不同,JComboBox会自动拥有一个mousebuttonListener,以便在点击时获得焦点? 如果不是,那么如何完全禁用JComboBox和当前卡显示的所有组件? 不可聚焦组件中的组件仍然可以聚焦是否是正常行为?

听起来你真正想要使用的是.setEnabled(false)

如果您需要将面板中的所有组件设置为禁用,那么您可以使用这样的方法来执行此操作:(可能不是JComponents的最佳方法,但如果需要可以轻松修改,但这确实有效)

 public static void setContainerAndChildrenEnabled(Container c, boolean b) { Component[] allComps = c.getComponents(); for(Component com : allComps) { com.setEnabled(b); if(com instanceof Container) setContainerAndChildrenEnabled((Container) com, b); } } 

然后使用要设置的面板调用它,使用true或false调用以启用/禁用。 这也将递归调用Container每个Component setEnabled()

从文档中有两点要注意:

  1. 注意:禁用轻量级组件不会阻止它接收MouseEvents。

  2. 注意:禁用重量级容器会阻止此容器中的所有组件接收任何输入事件。 但禁用轻量级容器只会影响此容器。

isLightweight()

我尝试了很多不同的方法来解决类似的问题。

步行组件层次结构和禁用每个组件的问题是您销毁任何上下文并绕过这些组件的管理。

基本上,如果在重新启用容器时某些子组件需要保持禁用状态,那么您突然陷入了多层交织责任的问题……

我发现迄今为止最好的解决方案是简单地使用JXLayer ,它提供了一个“可锁定”的层概念,允许您“锁定”单个容器,阻止用户与之交互,例如……

在此处输入图像描述

这是直接从JXLayer演示代码中获取的……

 /** * Copyright (c) 2006-2008, Alexander Potochkin * All rights reserved. */ package org.jdesktop.jxlayer.demo; import com.jhlabs.image.BlurFilter; import com.jhlabs.image.EmbossFilter; import org.jdesktop.jxlayer.JXLayer; import org.jdesktop.jxlayer.demo.util.LafMenu; import org.jdesktop.jxlayer.plaf.effect.BufferedImageOpEffect; import org.jdesktop.jxlayer.plaf.effect.LayerEffect; import org.jdesktop.jxlayer.plaf.ext.LockableUI; import org.jdesktop.swingx.painter.BusyPainter; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.Ellipse2D; /** * A demo to show the abilities of the {@link LockableUI}. * * @see BusyPainterUI */ public class LockableDemo extends JFrame { private JXLayer layer; private LockableUI blurUI = new LockableUI(new BufferedImageOpEffect(new BlurFilter())); private EnhancedLockableUI embossUI = new EnhancedLockableUI(new BufferedImageOpEffect(new EmbossFilter())); private LockableUI busyPainterUI = new BusyPainterUI(); private JCheckBoxMenuItem disablingItem = new JCheckBoxMenuItem(new AbstractAction("Lock the layer") { public void actionPerformed(ActionEvent e) { blurItem.setEnabled(!disablingItem.isSelected()); embossItem.setEnabled(!disablingItem.isSelected()); busyPainterItem.setEnabled(!disablingItem.isSelected()); blurUI.setLocked(disablingItem.isSelected()); embossUI.setLocked(disablingItem.isSelected()); busyPainterUI.setLocked(disablingItem.isSelected()); } }); private JRadioButtonMenuItem blurItem = new JRadioButtonMenuItem("Blur effect"); private JRadioButtonMenuItem embossItem = new JRadioButtonMenuItem("Unlock button"); private JRadioButtonMenuItem busyPainterItem = new JRadioButtonMenuItem("BusyPainter"); public LockableDemo() { super("Lockable layer demo"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JComponent view = createLayerPanel(); layer = new JXLayer(view); layer.setUI(blurUI); add(layer); add(createToolPanel(), BorderLayout.EAST); setJMenuBar(createMenuBar()); setSize(380, 300); setLocationRelativeTo(null); } public static void main(String[] args) throws Exception { SwingUtilities.invokeLater(new Runnable() { public void run() { new LockableDemo().setVisible(true); } }); } private JMenuBar createMenuBar() { JMenu menu = new JMenu("Menu"); disablingItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.ALT_MASK)); menu.add(disablingItem); menu.addSeparator(); blurItem.setSelected(true); blurItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.ALT_MASK)); menu.add(blurItem); embossItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, InputEvent.ALT_MASK)); menu.add(embossItem); busyPainterItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_3, InputEvent.ALT_MASK)); menu.add(busyPainterItem); ButtonGroup group = new ButtonGroup(); group.add(blurItem); group.add(embossItem); group.add(busyPainterItem); ItemListener menuListener = new ItemListener() { public void itemStateChanged(ItemEvent e) { if (blurItem.isSelected()) { layer.setUI(blurUI); } else if (embossItem.isSelected()) { layer.setUI(embossUI); } else if (busyPainterItem.isSelected()) { layer.setUI(busyPainterUI); } } }; blurItem.addItemListener(menuListener); embossItem.addItemListener(menuListener); busyPainterItem.addItemListener(menuListener); embossUI.getUnlockButton().addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { disablingItem.doClick(); } }); JMenuBar bar = new JMenuBar(); bar.add(menu); bar.add(new LafMenu()); return bar; } private JComponent createLayerPanel() { JComponent panel = new JPanel(); panel.add(new JCheckBox("JCheckBox")); panel.add(new JRadioButton("JRadioButton")); panel.add(new JTextField(15)); JButton button = new JButton("Have a nice day"); button.setMnemonic('H'); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(LockableDemo.this, "actionPerformed"); } }); panel.add(button); panel.add(new JTextField(15)); panel.add(new JCheckBox("JCheckBox")); panel.add(new JRadioButton("JRadioButton")); panel.add(new JTextField(15)); panel.add(new JCheckBox("JCheckBox")); panel.add(new JRadioButton("JRadioButton")); panel.setBorder(BorderFactory.createEtchedBorder()); return panel; } private JComponent createToolPanel() { JComponent box = Box.createVerticalBox(); JCheckBox button = new JCheckBox(disablingItem.getText()); button.setModel(disablingItem.getModel()); box.add(Box.createGlue()); box.add(button); box.add(Box.createGlue()); JRadioButton blur = new JRadioButton(blurItem.getText()); blur.setModel(blurItem.getModel()); box.add(blur); JRadioButton emboss = new JRadioButton(embossItem.getText()); emboss.setModel(embossItem.getModel()); box.add(emboss); JRadioButton translucent = new JRadioButton(busyPainterItem.getText()); translucent.setModel(busyPainterItem.getModel()); box.add(translucent); box.add(Box.createGlue()); return box; } /** * Subclass of the {@link LockableUI} which shows a button * that allows to unlock the {@link JXLayer} when it is locked */ public static class EnhancedLockableUI extends LockableUI { private JButton unlockButton = new JButton("Unlock"); public EnhancedLockableUI(LayerEffect... lockedEffects) { super(lockedEffects); unlockButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setLocked(false); } }); unlockButton.setVisible(false); } public AbstractButton getUnlockButton() { return unlockButton; } @Override @SuppressWarnings("unchecked") public void installUI(JComponent c) { super.installUI(c); JXLayer l = (JXLayer) c; l.getGlassPane().setLayout(new GridBagLayout()); l.getGlassPane().add(unlockButton); unlockButton.setCursor(Cursor.getDefaultCursor()); } @Override @SuppressWarnings("unchecked") public void uninstallUI(JComponent c) { super.uninstallUI(c); JXLayer l = (JXLayer) c; l.getGlassPane().setLayout(new FlowLayout()); l.getGlassPane().remove(unlockButton); } public void setLocked(boolean isLocked) { super.setLocked(isLocked); unlockButton.setVisible(isLocked); } } /** * Subclass of the {@link LockableUI} which uses the {@link BusyPainterUI} * from the SwingX project to implement the "busy effect" * when {@link JXLayer} is locked. */ public static class BusyPainterUI extends LockableUI implements ActionListener { private BusyPainter busyPainter; private Timer timer; private int frameNumber; public BusyPainterUI() { busyPainter = new BusyPainter() { protected void doPaint(Graphics2D g, JComponent object, int width, int height) { // centralize the effect Rectangle r = getTrajectory().getBounds(); int tw = width - r.width - 2 * rx; int th = height - r.height - 2 * ry; g.translate(tw / 2, th / 2); super.doPaint(g, object, width, height); } }; busyPainter.setPointShape(new Ellipse2D.Double(0, 0, 20, 20)); busyPainter.setTrajectory(new Ellipse2D.Double(0, 0, 100, 100)); timer = new Timer(100, this); } @Override protected void paintLayer(Graphics2D g2, JXLayer l) { super.paintLayer(g2, l); if (isLocked()) { busyPainter.paint(g2, l, l.getWidth(), l.getHeight()); } } @Override public void setLocked(boolean isLocked) { super.setLocked(isLocked); if (isLocked) { timer.start(); } else { timer.stop(); } } // Change the frame for the busyPainter // and mark BusyPainterUI as dirty public void actionPerformed(ActionEvent e) { frameNumber = (frameNumber + 1) % 8; busyPainter.setFrame(frameNumber); // this will repaint the layer setDirty(true); } } }