1

JDialogのJButtonコンポーネントにツールチップテキストを追加すると、ボタン(実際には、同様のことを行う2つのボタン)が無効になっているように機能します(setEnabled(false))。実際のツールチップテキストとは直接関係がなく、 EDTでループ内で何かを実行しているように感じます。とにかく、ここにクラスがあります。

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();
    }
}

明らかに、それは文脈なしではかなり混乱します。これは、拡張するDialogクラスです。

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);
        }
    });
}

ここで注意すべき重要な点は、init()がEDTの外部で呼び出され、 setToolTipText()メソッドが呼び出された場合にのみ動作が発生することです。同じ動作が、異なるが同様に構造化されたクラスで観察されます。

これはEDTで問題を引き起こしているループですか、それともツールチップテキストの動作に関連していますか?(私はtooltiptextを使用したことがなく、swing / javaを初めて使用します)

これ以上の情報が必要な場合は、質問してください。

ありがとう

4

2 に答える 2

2

まず、 の外部で UI コンポーネントを更新しないEDTでください。これには構築が含まれます。コンポーネントがいつ更新を要求して再描画を引き起こすか、または実際にいつネイティブ ピアにアタッチするかはわかりません。

EDTコンポーネントを内部の UI に追加する限り、外部でコンポーネントを初期化できると信じられていました。これは当時の誤解であり、実際に Swing 開発チームは、これは悪い習慣であると述べました。

Is it safe to construct Swing/AWT widgets NOT on the Event Dispatch Thread?を読みたいと思うかもしれません。詳細については

第 2 に、 で時間のかかるタスクを実行しないでください。実行するEDTと、 がEDTペイントやイベントの要求を処理できなくなり、UI が応答しないように見えます。

ループが実行されている時間を知らなければ、何とも言えません。私ができる最善の提案は、メソッドの実際の本体をコメントアウトして、actionPerformedもう一度テストすることです

于 2012-09-16T20:25:52.423 に答える
2

ここでの問題は、ラベルorderLabelが 2 つのボタンupdown. 強調表示する緑色の境界線を追加しました。

アプリのスナップショット

ボタンは無効にはなりませんがMouseListener、ツールチップのオーバーライドが設定されているため、マウス クリックはブロックされます。

解決策は、このラベルのツールチップを削除するか、ボタンと重ならないようにサイズを縮小することです。

于 2012-09-16T21:44:17.147 に答える