【问题标题】:How can a class extend both Thread and Gui?一个类如何同时扩展 Thread 和 Gui?
【发布时间】:2015-03-06 22:35:32
【问题描述】:

我想创建一个有两个按钮的 GUI,这样当第一个按钮被点击时,它的颜色会在蓝色和白色之间来回变化,当第二个按钮被点击时,它的颜色会在蓝色和白色之间来回变化黄色和绿色。我希望两个按钮的颜色变化能够同时发生,所以我创建了两个类 Button1 和 Button2,它们都扩展了 Thread 类。但是,我现在遇到一个问题:在 Button1/Button2 类中,您无法访问主类(Gui 类)中的 button1/button2。我希望 Button1/Button2 扩展 Thread 和 Gui,但这是不可能的; Java 不支持多重继承。 “public class Button1 extends Thread, Gui”和“public class Button1 extends Thread extends 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 类似(略)。

【问题讨论】:

  • 你的类应该都不扩展
  • 我认为您不了解 extends 所做的设计...也许您应该阅读一下 Inheritance 在 java 中的作用
  • 切题相关:为什么要在构造函数而不是 main 方法中初始化,为什么要在 Gui 类中创建 Gui 的新实例?
  • @mstbaum:请在上面解释您的评论。我不确定我是否看到了问题。
  • 另外,我认为您不了解并行性。按钮不应该是线程。该按钮应该启动一个异步任务。单击按钮时,将异步任务提交到线程池中。按钮单击以及任何其他 GUI 事件都应该发生在单个线程(GUI 线程)上。

标签: java multithreading swing user-interface


【解决方案1】:

你问:

一个类如何同时扩展 Thread 和 Gui?

你的类应该都不应该扩展。您的问题涉及几个问题,包括:

  • 您希望创建一个同时具有线程行为和 gui 行为的类,这强烈表明您正在创建一个“神”类,一个试图做太多事情的类。每个班级应该有一个单一的职责。
  • 为什么要扩展 Thread?最好创建实现 Runnable 的类,然后在线程中运行它。

你还说:

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

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

您的代码的其他问题:

  • 当您尝试从后台线程进行 Swing 调用时,您的线程代码不遵守 Swing 线程规则。
  • 最好跳过线程和 Thread.sleep(...) 并使用 Swing 计时器,因为这将为您提供所需的延迟,并且还可以很好地尊重 Swing 线程。

例如,以下代码使用 AbstractActions(将这些视为超级强大的 ActionListeners)代替 ActionListeners,并使用 Swing Timer 来交换 JButtons 的文本,具有不同的延迟时间。请注意,我不想发布完全解决您的作业的代码,而是向您展示我正在谈论的概念。

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

【讨论】:

    猜你喜欢
    • 2013-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-21
    • 2013-09-19
    • 1970-01-01
    相关资源
    最近更新 更多