我想通过单击带有以下代码的按钮来创建按钮:
addButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
projects_panel.add(new JButton("Button"));
revalidate();
repaint();
}
});
现在我想使用 TextField 更改按钮的文本,但是如何在不知道其名称的情况下访问特定的 UI 组件。
我尝试用附加到字符串的递增数字来命名按钮,但这不起作用。我还读到Java没有这个功能。
如何在没有变量名的情况下访问 Swing UI 组件?
/**
* This returns the first showing Component that matches a given name.
*
* @param components leave this completely empty to search ALL showing components.
*/
public static Component findComponentByName(String name, Component... components) {
Objects.requireNonNull(name);
if (components.length == 0)
components = Window.getWindows();
for (Component c : components) {
if (c.isShowing()) {
if (name.equals(c.getName())) {
return c;
} else if (c instanceof Container container) {
Component[] children = container.getComponents();
if (children.length > 0) {
Component returnValue = findComponentByName(name, children);
if (returnValue != null)
return returnValue;
}
}
}
}
return null;
}
(另外:记住 JComponent 的 name 和它的 text 不同。请参阅
JComponent.setName(String)
和 JButton.setText(String)
)
但是这种方法仍然让你离目标还很远:
现在我想用 TextField 更改按钮的文本
这里有一些潜在的入门代码:
package com.pump.winnow;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Objects;
/**
* This panel has an "Add Project" button. Every time you click it a new JButton is created. When it is first
* created: a JTextField sits on top of the JButton to let you edit the button's name. You can also enter this
* special editing mode by right-clicking the JButton.
*/
public class ProjectPanel extends JPanel {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame f = new JFrame();
f.getContentPane().add(new ProjectPanel());
f.pack();
f.setVisible(true);
}
});
}
/**
* This positions a JTextField over a button. It assumes the button will only ever have one child (the JTextField),
* or no children.
*/
static class ButtonTextEditorLayout implements LayoutManager {
private final JButton button;
private final Dimension prefSize, minSize;
public ButtonTextEditorLayout(JButton button) {
this.button = button;
prefSize = button.getUI().getPreferredSize(button);
minSize = button.getUI().getMinimumSize(button);
}
@Override
public void addLayoutComponent(String name, Component comp) {}
@Override
public void removeLayoutComponent(Component comp) {}
@Override
public Dimension preferredLayoutSize(Container parent) {
if (button != parent) throw new IllegalArgumentException();
if (button.getComponentCount() == 0)
return button.getUI().getPreferredSize(button);
return prefSize;
}
@Override
public Dimension minimumLayoutSize(Container parent) {
if (button != parent) throw new IllegalArgumentException();
if (button.getComponentCount() == 0)
return button.getUI().getMinimumSize(button);
return minSize;
}
@Override
public void layoutContainer(Container parent) {
if (button != parent) throw new IllegalArgumentException();
if (button.getComponentCount() == 1) {
JTextField field = (JTextField) button.getComponent(0);
Insets buttonInsets = button.getInsets();
Insets fieldInsets = field.getInsets();
field.setBounds(new Rectangle(buttonInsets.left - fieldInsets.left,
buttonInsets.top - fieldInsets.top,
button.getWidth() - buttonInsets.left - buttonInsets.right + fieldInsets.left + fieldInsets.right,
button.getHeight() - buttonInsets.top - buttonInsets.bottom + fieldInsets.top + fieldInsets.bottom));
}
}
}
JPanel toolbar = new JPanel();
JButton addButton = new JButton("Add Project");
JPanel content = new JPanel(new FlowLayout());
public ProjectPanel() {
toolbar.setBackground(Color.gray);
setLayout(new BorderLayout());
add(toolbar, BorderLayout.NORTH);
add(content, BorderLayout.CENTER);
toolbar.setLayout(new FlowLayout());
toolbar.add(addButton);
addButton.addActionListener(e -> {
String projectName = "Project #" + (content.getComponentCount() + 1);
JButton projectButton = new JButton(projectName);
content.add(projectButton);
setupButtonTextEditor(projectButton);
revalidate();
projectButton.addMouseListener(new MouseAdapter() {
// IIRC different platforms use different mouse events as popup triggers
@Override
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger())
setupButtonTextEditor(projectButton);
}
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger())
setupButtonTextEditor(projectButton);
}
});
});
setPreferredSize(new Dimension(400, 400));
}
private void setupButtonTextEditor(JButton button) {
JTextField field = new JTextField(button.getText());
field.setBorder(null);
field.setFont(button.getFont());
field.addActionListener(e -> {
removeTextField(button, field);
});
field.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
removeTextField(button, field);
}
});
button.setLayout(new ButtonTextEditorLayout(button));
button.add(field);
field.selectAll();
field.requestFocus();
button.revalidate();
}
private void removeTextField(JButton button, JTextField field) {
if (field.getParent() == button) {
button.remove(field);
button.setText(field.getText());
button.repaint();
}
}
}
我需要模型或更多描述来了解如何更好地实现您的目标。我可能(?)倾向于为每个项目创建一个自定义 JPanel,并在该面板中嵌入一个永久的 JTextField。