Java 工具提示文本呈现为不可链接的JButton
当我将工具提示文本添加到JDialog中的JButton组件时,按钮(实际上,两个执行类似操作的按钮)的行为就像它被禁用一样(setEnabled(false))。我感觉它与实际的工具提示文本没有直接关系,而是在EDT上循环执行某些操作。不管怎样,这就是课堂Java 工具提示文本呈现为不可链接的JButton,java,swing,jbutton,event-dispatch-thread,Java,Swing,Jbutton,Event Dispatch Thread,当我将工具提示文本添加到JDialog中的JButton组件时,按钮(实际上,两个执行类似操作的按钮)的行为就像它被禁用一样(setEnabled(false))。我感觉它与实际的工具提示文本没有直接关系,而是在EDT上循环执行某些操作。不管怎样,这就是课堂 package org.carroll.dialogs.editing; import java.awt.Dimension; import java.awt.Font; import java.awt.GridBagConstraint
package org.carroll.dialogs.editing;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JTextField;
import org.carroll.data.school.AllCourses;
import org.carroll.data.settings.Settings;
import org.carroll.internal.InternalPanel;
import org.carroll.school.Course;
import org.carroll.utils.Logging;
import org.swing.Dialog;
import org.swing.Listeners;
import org.swing.dialogs.messages.ErrorMessage;
/**
* Dialog for editing a course. Is custom to editing courses.
*
* @author Joel Gallant
*/
public class EditCourseDialog extends Dialog {
JButton save, done, cancel;
KeyListener doneListener = new Listeners.DoneListener() {
@Override
public void enterPressed() {
if (!done.isFocusOwner()) {
done.doClick();
}
}
};
static Course currentCourse;
/**
* Creates dialog with default course selected.
*/
public EditCourseDialog() {
super("Edit Course");
currentCourse = AllCourses.getInstance().get(0);
}
/**
* Creates dialog that selects a course by default.
*
* @param startingSelection default selection
*/
public EditCourseDialog(String startingSelection) {
super("Edit Course");
try {
currentCourse = AllCourses.getInstance().get(startingSelection);
} catch (NoSuchFieldException ex) {
currentCourse = AllCourses.getInstance().get(0);
}
}
public EditCourseDialog(Course startingCourse) {
super("Edit Course");
currentCourse = startingCourse;
}
void editCourse(String name, int credits, int units, int[] semester, int order) {
Logging.log(name + " edited.");
currentCourse.setName(name);
currentCourse.setCredits(credits);
currentCourse.setUnits(units);
currentCourse.setSemester(semester);
currentCourse.setOrder(order);
if (!AllCourses.getInstance().getElements().contains(currentCourse)) {
AllCourses.getInstance().add(currentCourse);
}
InternalPanel.COURSES.refresh();
}
@Override
protected void init() {
GridBagLayout layout = new GridBagLayout();
setLayout(layout);
setPreferredSize(new Dimension(385, 280));
Integer[] creditArray = {1, 3, 5};
String[] semesterArray;
try {
semesterArray = new String[Integer.parseInt(Settings.getInstance().get("Semesters").getValue()) + 1];
for (int x = 0; x < Integer.parseInt(Settings.getInstance().get("Semesters").getValue()); x++) {
semesterArray[x] = String.valueOf(x + 1);
}
semesterArray[semesterArray.length - 1] = "Year";
} catch (NoSuchFieldException ex) {
semesterArray = new String[2];
semesterArray[0] = "1";
semesterArray[1] = "2";
}
final JComboBox<String> course = new JComboBox<>(AllCourses.getInstance().getNames());
final JLabel nameLabel = new JLabel("Name"),
creditsLabel = new JLabel("Credits"),
unitsLabel = new JLabel("Units"),
semesterLabel = new JLabel("Semester"),
orderLabel = new JLabel("Order");
final JTextField name = new JTextField(),
units = new JTextField(),
order = new JTextField();
final JButton up = new JButton("↑"),
down = new JButton("↓");
final JComboBox<Integer> credits = new JComboBox<>(creditArray);
final JComboBox<String> semester = new JComboBox<>(semesterArray);
save = new JButton("Save");
done = new JButton("Done");
cancel = new JButton("Cancel");
course.setSelectedItem(currentCourse.getName());
String orderExpl = "<html>The order you are doing the courses in during the semester. "
+ "<br>It starts at 1, and goes on. (Do not make multiple courses with same order)</html>";
orderLabel.setToolTipText(orderExpl);
order.setToolTipText(orderExpl);
up.setToolTipText(orderExpl);
down.setToolTipText(orderExpl);
name.setText(currentCourse.getName());
name.setCaretPosition(0);
units.setText(String.valueOf(currentCourse.getUnits()));
credits.setSelectedItem(currentCourse.getCredits());
semester.setSelectedItem(currentCourse.getSemesters().length > 1 ? "Year" : String.valueOf(currentCourse.getSemesters()[0]));
order.setText(String.valueOf(currentCourse.getOrder()));
up.setFont(up.getFont().deriveFont(Font.BOLD, (float) 14));
down.setFont(up.getFont());
course.addKeyListener(doneListener);
name.addKeyListener(doneListener);
units.addKeyListener(doneListener);
credits.addKeyListener(doneListener);
semester.addKeyListener(doneListener);
order.addKeyListener(doneListener);
done.addKeyListener(doneListener);
cancel.addKeyListener(doneListener);
save.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
int[] semesters;
if (semester.getSelectedItem().equals("Year")) {
semesters = new int[Integer.parseInt(Settings.getInstance().get("Semesters").getValue())];
for (int x = 0; x < semesters.length; x++) {
semesters[x] = x + 1;
}
} else {
semesters = new int[]{Integer.parseInt(semester.getSelectedItem().toString())};
}
editCourse(name.getText(), Integer.parseInt(credits.getSelectedItem().toString()),
Integer.parseInt(units.getText()), semesters,
Integer.parseInt(order.getText()));
} catch (NumberFormatException ex) {
new ErrorMessage(ex, "A number was entered wrong").createAndViewGUI();
} catch (NoSuchFieldException ex) {
new ErrorMessage(ex).createAndViewGUI();
}
}
});
done.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
int[] semesters;
if (semester.getSelectedItem().equals("Year")) {
semesters = new int[Integer.parseInt(Settings.getInstance().get("Semesters").getValue())];
for (int x = 0; x < semesters.length; x++) {
semesters[x] = x + 1;
}
} else {
semesters = new int[]{Integer.parseInt(semester.getSelectedItem().toString())};
}
editCourse(name.getText(), Integer.parseInt(credits.getSelectedItem().toString()),
Integer.parseInt(units.getText()), semesters,
Integer.parseInt(order.getText()));
dispose();
} catch (NumberFormatException ex) {
new ErrorMessage(ex, "A number was entered wrong").createAndViewGUI();
} catch (NoSuchFieldException ex) {
new ErrorMessage(ex).createAndViewGUI();
}
}
});
cancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dispose();
}
});
up.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
AllCourses.getInstance().move(currentCourse.getName(), true);
order.setText(String.valueOf(currentCourse.getOrder()));
InternalPanel.COURSES.refresh();
}
});
down.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
AllCourses.getInstance().move(currentCourse.getName(), false);
order.setText(String.valueOf(currentCourse.getOrder()));
InternalPanel.COURSES.refresh();
}
});
course.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
try {
currentCourse = AllCourses.getInstance().get(course.getSelectedItem().toString());
} catch (NoSuchFieldException ex) {
currentCourse = AllCourses.getInstance().get(course.getSelectedIndex());
}
name.setText(currentCourse.getName());
units.setText(String.valueOf(currentCourse.getUnits()));
credits.setSelectedItem(currentCourse.getCredits());
semester.setSelectedItem(currentCourse.getSemesters().length > 1 ? "Year" : String.valueOf(currentCourse.getSemesters()[0]));
order.setText(String.valueOf(currentCourse.getOrder()));
}
});
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.BOTH;
constraints.insets = new Insets(5, 8, 5, 8);
constraints.weightx = 1;
constraints.weighty = 1;
constraints.gridwidth = 4;
layout.addLayoutComponent(course, constraints);
constraints.gridy = 1;
constraints.gridwidth = 1;
layout.addLayoutComponent(nameLabel, constraints);
constraints.gridx = 1;
constraints.gridwidth = 3;
layout.addLayoutComponent(name, constraints);
constraints.gridy = 2;
constraints.gridx = 0;
constraints.gridwidth = 1;
layout.addLayoutComponent(creditsLabel, constraints);
constraints.gridx = 1;
constraints.gridwidth = 3;
layout.addLayoutComponent(credits, constraints);
constraints.gridx = 0;
constraints.gridy = 3;
constraints.gridwidth = 1;
layout.addLayoutComponent(unitsLabel, constraints);
constraints.gridx = 1;
constraints.gridwidth = 3;
layout.addLayoutComponent(units, constraints);
constraints.gridy = 4;
constraints.gridx = 0;
constraints.gridwidth = 1;
layout.addLayoutComponent(semesterLabel, constraints);
constraints.gridx = 1;
constraints.gridwidth = 3;
layout.addLayoutComponent(semester, constraints);
constraints.gridy = 5;
constraints.gridx = 0;
layout.addLayoutComponent(orderLabel, constraints);
constraints.gridx = 1;
constraints.gridwidth = 1;
layout.addLayoutComponent(up, constraints);
constraints.gridx = 2;
layout.addLayoutComponent(down, constraints);
constraints.gridx = 3;
layout.addLayoutComponent(order, constraints);
constraints.gridy = 6;
constraints.gridx = 0;
layout.addLayoutComponent(save, constraints);
constraints.gridx = 1;
constraints.gridwidth = 2;
layout.addLayoutComponent(done, constraints);
constraints.gridx = 3;
constraints.gridwidth = 1;
layout.addLayoutComponent(cancel, constraints);
add(course);
add(nameLabel);
add(name);
add(creditsLabel);
add(credits);
add(unitsLabel);
add(units);
add(semesterLabel);
add(semester);
add(orderLabel);
add(up);
add(down);
add(order);
add(save);
add(done);
add(cancel);
}
@Override
public void createAndViewGUI() {
if (currentCourse != null) {
super.createAndViewGUI();
} else {
new ErrorMessage(new NoSuchFieldException("No courses"), "No courses to edit").createAndViewGUI();
}
}
这里需要注意的重要一点是init()是在EDT之外调用的,并且只有在调用setToolTiptText()方法时才会发生这种行为。在不同但结构相似的类中观察到相同的行为
这是导致EDT中出现问题的循环还是与工具提示文本的工作方式有关?(我从未使用过tooltiptext,而且对swing/java非常陌生)
如需更多信息,请询问
感谢首先,切勿更新EDT以外的任何UI组件,这包括构造,您不知道组件何时会请求更新并导致重新绘制,或者何时实际连接到本机对等机 过去人们认为,只要将组件添加到其中的UI中,就可以在
EDT
之外初始化组件。这在当时是一种误解,Swing开发团队实际上表示这是一种糟糕的做法
您可能想阅读更多详细信息
其次,切勿在EDT
中执行任何耗时的任务,它们将阻止EDT
处理绘制和事件请求,使UI看起来没有响应
如果不知道循环运行了多长时间,就无法确定。我能提出的最好建议是注释掉
actionPerformed
方法的实际主体,然后再次测试它首先,不要更新EDT
之外的任何UI组件,这包括构造,您不知道组件何时会请求更新并导致重新绘制,也不知道它何时实际连接到本机对等机
过去人们认为,只要将组件添加到其中的UI中,就可以在EDT
之外初始化组件。这在当时是一种误解,Swing开发团队实际上表示这是一种糟糕的做法
您可能想阅读更多详细信息
其次,切勿在EDT
中执行任何耗时的任务,它们将阻止EDT
处理绘制和事件请求,使UI看起来没有响应
如果不知道循环运行了多长时间,就无法确定。我能提出的最佳建议是注释掉执行的
操作方法的实际主体,然后再次测试它这里的问题是您的标签orderLabel
在两个按钮上展开,up
和down
。我添加了一个绿色边框以突出显示:
按钮未被禁用,但鼠标单击被阻止,因为工具提示现在有一个覆盖的MouseListener
解决方案是删除此标签的工具提示,或者缩小其大小,使其不会与按钮重叠。这里的问题是,您的标签orderLabel
在两个按钮上展开,up
和down
。我添加了一个绿色边框以突出显示:
按钮未被禁用,但鼠标单击被阻止,因为工具提示现在有一个覆盖的MouseListener
解决方案是删除此标签的工具提示,或者缩小其大小,使其不会与按钮重叠。谢谢您的建议。我最近刚刚了解了EDT,正如你所知道的,我还没有考虑到它。谢谢你的建议。我最近刚刚了解了EDT,正如你所知道的,我还没有考虑到它。
package org.swing;
import java.awt.Component;
import java.awt.event.WindowEvent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
import org.carroll.dialogs.MainFrame;
/**
* Basic interface for all user dialogs. Extends {@link JFrame}.
*
* @author Joel Gallant
*/
public abstract class Dialog extends JDialog {
Component c = null;
/**
* Creates a basic dialog that disposes on closing.
*
*/
public Dialog() {
super(MainFrame.getInstance());
}
/**
* Creates a basic dialog that disposes on closing.
*
* @param location relative position of the window
*/
public Dialog(Component location) {
this();
this.c = location;
}
/**
* Creates a basic dialog that disposes on closing.
*
* @param title title of the dialog
*/
public Dialog(String title) {
super(MainFrame.getInstance(), title);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
/**
* Creates a basic dialog that disposes on closing.
*
* @param title title of the dialog
* @param location relative position of the window
*/
public Dialog(String title, Component location) {
super(MainFrame.getInstance(), title);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
this.c = location;
}
/**
* Creates a basic dialog which follows the default close operation given in
* the parameter.
*
* @param title title of the dialog
* @param defaultCloseOperation default closing operation of the window
*/
public Dialog(String title, int defaultCloseOperation) {
super(MainFrame.getInstance(), title);
setDefaultCloseOperation(defaultCloseOperation);
}
/**
* Creates a basic dialog which follows the default close operation given in
* the parameter.
*
* @param title title of the dialog
* @param defaultCloseOperation default closing operation of the window
* @param location relative position of the window
*/
public Dialog(String title, int defaultCloseOperation, Component location) {
this(title, defaultCloseOperation);
this.c = location;
}
/**
* Initializes everything needed to display the GUI.
*/
protected abstract void init();
@Override
public void dispose() {
super.dispose();
dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSED));
}
/**
* Create all necessary components of the dialog and display it.
*/
public void createAndViewGUI() {
init();
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
pack();
setLocationRelativeTo(c);
setVisible(true);
}
});
}