首页 文章

一个类如何扩展Thread和Gui?

提问于
浏览
1

我想用两个按钮创建一个GUI,这样当点击第一个按钮时,它的颜色会在蓝色和白色之间来回变化,当点击第二个按钮时,它的颜色会在黄色和绿色之间来回变换 . 我希望两个按钮的颜色变化能够同时发生,所以我创建了两个类Button1和Button2,两者都扩展了Thread类 . 但是,我现在遇到一个问题:在Button1 / Button2类中,你无法访问主类(类Gui)中的button1 / button2 . 我希望Button1 / Button2扩展Thread和Gui,但这是不可能的; Java不支持多重继承 . 既没有“公共类Button1扩展Thread,Gui”也没有“公共类Button1扩展Thread扩展Gui”的作品 . 我该如何解决这个问题?

这是我的代码:

Gui.java:

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.io.*;

public class Gui implements ActionListener{
    private JFrame frame;
    private JButton button1;
    private JButton button2;
    private Button1 buttonone;
    private Button2 buttontwo;
    public Gui(){
        frame = new JFrame("");
        frame.setVisible(true);
        frame.setSize(500,500);
        buttonone = new Button1();
        buttontwo = new Button2();
        button1 = new JButton("button1");
        button2 = new JButton("button2");
        button1.addActionListener(this);
        button2.addActionListener(this);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container container = frame.getContentPane();
        container.setLayout(new FlowLayout());
        container.add(button1);
        container.add(button2);
    }

    public static void main(String[] args){
        Gui gui = new Gui();
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == button1) {
            buttonone.start();
        }
        if (e.getSource() == button2) {
            buttontwo.start();
        }
    }
}

Button1.java:

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.io.*;

public class Button1 extends Thread
{
    public void run(){
        while (true){
            button1.setBackground(Color.blue); //here's where the problem is
            try{
                Thread.sleep(1000);
            }
            catch(InterruptedException e){
                e.printStackTrace();
            }
            button1.setBackground(Color.white);
            try{
                Thread.sleep(1000);
            }
            catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

Button2.java类似(省略) .

1 回答

  • 7

    你问:

    一个类如何扩展Thread和Gui?

    你的 class 应该扩展 neither . 您的问题涉及几个问题,包括:

    • 您希望创建一个既具有线程行为又具有gui行为的类,这强烈表明您正在创建一个"god"类,一个试图做太多的类 . 每个 class 都应该有 single 责任 .

    • 为什么要扩展Thread?创建实现Runnable的类然后在线程中运行它会好得多 .

    你也说:

    但是,我现在遇到一个问题:在Button1 / Button2类中,你无法访问主类(类Gui)中的button1 / button2 . 我希望Button1 / Button2扩展Thread和Gui,但这是不可能的;

    但这是对继承的滥用 . 您不使用继承来“访问”另一个对象的字段,如果您尝试这样做,您的代码通常会编译但不起作用,因为访问的gui对象不是显示的对象 . 相反,你想使用composition - 将一个对象的引用传递给另一个对象

    您的代码的其他问题:

    • 当您尝试从后台线程进行Swing调用时,您的线程代码不遵守Swing线程规则 .

    • 更好的是跳过线程和 Thread.sleep(...) 并使用Swing Timer,因为这将为您提供所需的延迟,并且还将很好地尊重Swing线程 .


    例如,下面的代码使用AbstractActions(将它们视为超级动力的ActionListeners)代替ActionListeners,使用Swing Timer来交换JButton的文本,具有不同的延迟时间 . 请注意,我不想发布完全解决您的任务的代码,而是向您展示我正在谈论的概念 .

    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.*;
    
    public class ButtonFoo extends JPanel {
    
       public ButtonFoo() {
          setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
          setLayout(new GridLayout(1, 0, 5, 5));
          add(new JButton(new SwapAction("Swap", "Fu", 1000)));
          add(new JButton(new SwapAction("Snafu", "Fubar", 200)));
          add(new JButton(new SwapAction("Goodbye", "Hello", 50)));
       }
    
       private static void createAndShowGui() {
          JFrame frame = new JFrame("ButtonFoo");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.getContentPane().add(new ButtonFoo());
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }
    
    class SwapAction extends AbstractAction {
       private String text1;
       private String text2;
       private int delay;
       private Timer timer;
    
       public SwapAction(String text1, String text2, int delay) {
          super(text1);
          this.text1 = text1;
          this.text2 = text2;
          this.delay = delay;
    
          timer = new Timer(delay, new TimerListener());
       }
    
       @Override
       public void actionPerformed(ActionEvent e) {
          if (timer.isRunning()) {
             timer.stop();
          } else {
             timer.start();
          }
       }
    
       private class TimerListener implements ActionListener {
          private boolean firstText = true;
    
          @Override
          public void actionPerformed(ActionEvent e) {
             firstText = !firstText; //toggle boolean
             String newName = firstText ? text1 : text2;
             putValue(NAME, newName);
          }
       }
    }
    

相关问题