- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
有没有办法让 JComponent
获取其后代组件层次结构中添加/删除更改的通知?
例如,在下面的代码中,有一个 addChild
按钮,它将向根或最后添加的面板添加一个新的子 JPanel
。我希望根面板能够收到此通知。有点像 HierarchyListener
但相反,或者是 ContainerListener
,它不仅仅监听直接子级。
public class DecendantHierarchyListening extends JFrame {
private final JPanel root = createChildPanel(null);
public JPanel leafComponent = root;
public DecendantHierarchyListening() {
super("title");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent buttons = new JPanel();
JPanel panel = new JPanel(new BorderLayout());
panel.add(createAddChildButton(buttons), BorderLayout.NORTH);
panel.add(root, BorderLayout.CENTER);
getContentPane().add(panel);
}
private Button createAddChildButton(JComponent buttons) {
Button button = new Button("AddChild");
buttons.add(button);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
leafComponent = (JPanel) leafComponent
.add(createChildPanel(leafComponent));
DecendantHierarchyListening.this.invalidate();
DecendantHierarchyListening.this.validate();
DecendantHierarchyListening.this.repaint();
}
});
return button;
}
public static JPanel createChildPanel(Container parent) {
Color[] colors = new Color[] { Color.RED, Color.BLUE, Color.GREEN };
JPanel panel = new JPanel(new BorderLayout());
panel.setPreferredSize(new Dimension(200, 200));
Color color;
if (parent == null) {
color = Color.GREEN;
} else {
int distance = 1;
parent = parent.getParent();
while (parent != null) {
distance++;
parent = parent.getParent();
}
color = colors[distance % colors.length];
}
panel.setBorder(BorderFactory.createLineBorder(color, 2));
return panel;
}
public static void runDemo() {
JFrame f = new DecendantHeirarchyListening();
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
DecendantHierarchyListening.runDemo();
}
}
最佳答案
一种可能的解决方案是使用单个ContainerListener
,它将自身添加到添加到“根”容器的容器中(并且,为了完整起见,还会将其自身从已删除的容器中删除,如果这是必要的)。
所以你基本上可以创建一个ContainerListener
并将其添加到根容器中。每当此监听器收到有关添加的新子组件的通知时,它也会将自身添加到此组件(如果它是容器)。稍后,当将组件添加到子组件时,监听器将收到通知,并可能再次将其自身添加到孙组件,依此类推。
我在这里举了一个例子:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DescendantHierarchyListening extends JPanel
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
public static void createAndShowGUI()
{
JFrame f = new JFrame();
f.add(new DescendantHierarchyListening());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(400, 400);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
ContainerListener containerListener = new ContainerListener()
{
@Override
public void componentAdded(ContainerEvent e)
{
Component child = e.getChild();
System.out.println("Added " + child);
System.out.println(" to " + e.getContainer());
if (child instanceof Container)
{
Container container = (Container)child;
container.addContainerListener(this);
}
}
@Override
public void componentRemoved(ContainerEvent e)
{
Component child = e.getChild();
System.out.println("Removed " + child);
System.out.println(" from " + e.getContainer());
if (child instanceof Container)
{
Container container = (Container)child;
container.removeContainerListener(this);
}
}
};
private final JPanel root;
public JPanel leafComponent;
public DescendantHierarchyListening()
{
super(new BorderLayout());
JButton button = createAddChildButton();
add(button, BorderLayout.NORTH);
root = createChildPanel(null);
root.addContainerListener(containerListener);
add(root, BorderLayout.CENTER);
leafComponent = root;
}
private JButton createAddChildButton()
{
JButton button = new JButton("AddChild");
button.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
JPanel child = createChildPanel(leafComponent);
leafComponent.add(child);
leafComponent = child;
revalidate();
}
});
return button;
}
public JPanel createChildPanel(final Container parent)
{
JPanel panel = new JPanel(new BorderLayout())
{
@Override
public String toString()
{
return "Child of " + parent;
}
};
Color color = getColor(parent);
panel.setBorder(BorderFactory.createLineBorder(color, 2));
return panel;
}
private static Color getColor(Component c)
{
if (c == null)
{
return Color.GREEN;
}
Color[] colors = new Color[]
{ Color.RED, Color.BLUE, Color.GREEN };
int d = getDepth(c);
return colors[d % colors.length];
}
private static int getDepth(Component c)
{
if (c == null)
{
return 0;
}
return 1 + getDepth(c.getParent());
}
}
关于java - 监听后代组件层次结构的变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25571162/
我有一个表(id, parent_id, data),其中parent_id 指向同一表中的另一行(或者为空)。 是否有一种标准的方法来查询(1)某个 id 的所有祖先和(2)某个 id 的所有后代?
networkx 中是否有函数/方法来识别给定(可选加权)距离内的所有祖先/后代? 例如,可以有效地产生与下面的函数相同的结果的东西? import networkx g = networkx.DiG
在我的窗口事件中,如果指针点击父对象或其子对象/后代对象,它应该做一些事情。问题是事件无法访问 parent 的 child 和孙子。条件存储在 targetIsInsideParent 变量中。 H
我有一个非常好的 DirectMySQL 单元,可以使用,我希望它成为 TDataset 的后代,这样我就可以将它与 QuickReport 一起使用,我只想要使用来自 TDataset 的 Dire
我将 mysql 表定义为: 类别:category_id、category_name、parent_category_id 我正在寻找一个很好的 sql 查询来检索给定 category_id 的所
我的 TCustomControl 后代使用线程,这涉及使用 InvalidateRect 进行无效化。我遇到这样的情况:当线程正在工作时关闭程序时,我不会停止 Destroy 中的线程,因为即使在进
我的 TMemo 后代有构造函数 constructor TMyMemo.Create(AOwner: TComponent); begin inherited Create(AOwner);
我正在尝试创建一个像Delphi 2009的TButtonedEdit这样的组件。它是一个自定义的TEdit,左右各有2个按钮。 在我的版本中,我使用 2 个 TSpeedButton 对象作为左右按
我遇到了一些问题,看起来使用 JQuery 应该很容易做到。基本上我的页面上有一个表格。表格中的每一行都有一个复选框和一个金额单元格。我正在尝试编写一个函数来遍历每一行并检查复选框是否已选中。如果是这
如何使用 linq 对包含相同对象的子集合 X 层深的对象集合获得与 doc.Descendants() 类似的功能? 最后一个嵌套集合包含需要获取的数据,所有其他父集合只是分组。我可以将集合转换为
我有一个引用自身的表,如下所示: CREATE TABLE Foo ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, parent INT NULL, nam
我正在尝试添加以下约束来对齐表格单元格内的图像。 self 指的是 ImageView 将驻留在其中的 UITableViewCell 对象: var imageViewTest = UIIm
我有以下标记: content Link Link Link
这里是一个简化的mxl结构'xml', Alice30 Bob31 Charley29 Dory25 这是我尝试过的; XmlDocument submiss
我正在尝试编写一个类,该类将在其对象创建时运行一个线程,并在对象被删除后停止该线程。 class MyThread : public boost::thread { public: MyThr
我有一个表 width: 100%以及该表中的元素 width: 40em; max-width: 100% , 但当浏览器窗口太小时,该元素仍在拉伸(stretch)表格。 我希望这个元素的宽度固定
我正在尝试在 Delphi 2007 中创建基于 TCustomComboBox 的自定义控件,但我陷入了第一个障碍。 我试图覆盖下拉列表的显示方式,主要是显示的文本,查看 stdctrls.pas
我正在尝试创建一个具有集合属性的自定义组件。但是,如果我尝试在设计时通过单击对象检查器中的“...”按钮来打开集合编辑器,则不会发生任何情况。我缺少什么? 这是我的 TCollection 后代:
我正在使用WPF DataGrid,并放置了DataGridTemplateColumn。因为该列应该对复杂类型(这是一个对象)执行编辑,所以我决定放置一个打开弹出窗口的切换按钮。代码如下:
我有一个基本的 UserControl (BaseControl.cs),上面有一个 OK 和 Cancel 按钮。单击按钮时,将触发一个事件。通常其他 UserControl 对象继承自 BaseC
我是一名优秀的程序员,十分优秀!