Java 与多个容器共享组件
我有JTabbedPane,每个选项卡都有一个JTextPane 每个JTextPane都有一个弹出菜单,但我希望它们共享完全相同的弹出菜单。为什么?因为当我切换选项卡时,我希望在每个弹出窗口上突出显示相同的选项 我该怎么做?我尝试在每个窗格中添加一个静态PopupMenu实例,但当我将其添加到一个窗格中时,它从其他窗格中消失 编辑:在以下SSCCE中,当在TabOne上选中复选框时,在Tab2上不选中该复选框。我想在两个标签上都检查一下。除此之外,每个选项卡的所有其他选项都是唯一的 SSCCE:Java 与多个容器共享组件,java,swing,jtabbedpane,jpopupmenu,Java,Swing,Jtabbedpane,Jpopupmenu,我有JTabbedPane,每个选项卡都有一个JTextPane 每个JTextPane都有一个弹出菜单,但我希望它们共享完全相同的弹出菜单。为什么?因为当我切换选项卡时,我希望在每个弹出窗口上突出显示相同的选项 我该怎么做?我尝试在每个窗格中添加一个静态PopupMenu实例,但当我将其添加到一个窗格中时,它从其他窗格中消失 编辑:在以下SSCCE中,当在TabOne上选中复选框时,在Tab2上不选中该复选框。我想在两个标签上都检查一下。除此之外,每个选项卡的所有其他选项都是唯一的 SSCCE
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;
public class Main {
public static void main(String[] Args) {
final Main M = new Main();
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
JFrame F = new JFrame("SSCCE");
JTabbedPane Pane = new JTabbedPane();
Pane.addTab("TabOne", M.new DebugBox(500, 500));
Pane.addTab("TabTwo", M.new DebugBox(500, 500));
F.setLayout(new BorderLayout());
F.add(Pane, BorderLayout.NORTH);
F.pack();
F.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
F.setVisible(true);
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
public class DebugBox extends JTextPane {
private JScrollPane ScrollPane = null;
private final JPopupMenu Menu = new JPopupMenu();
private static final long serialVersionUID = 7731036968185936516L;
public DebugBox(int Width, int Height) {
this.ScrollPane = new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
this.setPreferredSize(new Dimension(Width, Height));
JCheckBoxMenuItem Debug = new JCheckBoxMenuItem(new AbstractAction() {
private static final long serialVersionUID = -336209978671944858L;
@Override
public void actionPerformed(ActionEvent e) {
//DO something here that affects ALL the DebugBoxes because they all share this Menu Option somehow :S
//Change name of this menu option, all instances have their names changed too.
}
});
JMenuItem Copy = new JMenuItem(new AbstractAction() {
private static final long serialVersionUID = -6774461986513304498L;
@Override
public void actionPerformed(ActionEvent e) {
DebugBox.this.copy();
}
});
JMenuItem Clear = new JMenuItem(new AbstractAction() {
private static final long serialVersionUID = -5567371173360543484L;
@Override
public void actionPerformed(ActionEvent e) {
DebugBox.this.setText(null);
}
});
JMenuItem SelectAll = new JMenuItem(new AbstractAction() {
private static final long serialVersionUID = -8792250195980016624L;
@Override
public void actionPerformed(ActionEvent e) {
DebugBox.this.selectAll();
}
});
this.Menu.add(Copy);
this.Menu.add(Clear);
this.Menu.add(SelectAll);
this.Menu.add(Debug);
Copy.setText("Copy");
Clear.setText("Clear");
SelectAll.setText("Select All");
Debug.setText("Show Debug Box");
this.setEditable(false);
this.add(this.Menu);
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
DebugBox.this.Menu.show(DebugBox.this, e.getX(), e.getY());
}
}
});
}
}
}
如果要共享对象,则需要创建该对象并将该对象作为参数传递给其他类。比如:
JPopupMenu popup = createSharedPopupMenu();
Pane.addTab("TabOne", M.new DebugBox(500, 500, popup));
Pane.addTab("TabTwo", M.new DebugBox(500, 500, popup));
然后,您需要创建对任何文本组件都有效的通用操作。DefaultEditorIt为您提供以下一些操作:
public JPopupMenu createSharedPopupMenu()
{
JPopupMenu popup = new JPopupMenu()
JMenuItem copy = new JMenuItem( new DefaultEditorKit.CopyAction() );
popup.add( copy );
...
return popup.
}
如果编辑器工具包没有为您提供操作,那么您需要创建自己的操作,并且应该扩展TextAction
,而不是AbstractAction。TextAction类有一个方法,该方法将返回具有焦点的文本组件。因此,您可以以通用的方式实现该操作
此外,您不需要使用鼠标侦听器来调用弹出窗口。您可以只使用以下JComponent方法:
JComponent.setComponentPopupMenu(JPopupMenu popup)
您能否提供您的工作流程…可能重复:。你能告诉我你是如何按照@madprogrammer处理弹出菜单的吗?写了一篇又快又脏的SSCCE。我刚刚编辑了这篇文章。如果你想让其他人阅读你的代码,请使用标准的Java命名约定。变量名不应以大写字符开头。Hmm。。我很抱歉。在C、C++、ASM等所有程序中。当许多其他语言使用与Java完全不同的约定时,很难“切换”约定。我会试试的。我一定会改为查看TextAction。我无法将该对象作为参数传递,因为该对象一次只能包含在一个容器中。当添加到第二个容器时,它将从第一个容器中删除:(这是正确的,但是弹出菜单一次只能在一个组件上显示。它不是永久性地添加到容器中的。您所传递的只是对组件的引用,以便可以根据需要显示/隐藏弹出窗口。最佳答案!我没有想到这一点。起初,我制作了一个静态的最终弹出菜单,并为每个J添加了一个侦听器。)但是这个答案是最好的。我将重新写它以适应这个答案。