如何将实时时间添加到 JPanel 以及何时将按钮按下时间添加到其他 JPanel?

问题描述

代码的目的是使时间和毫秒始终运行。当按钮按下时,此时绿色面板上会出现当前时间。我截图了。

我的应用程序必须如下所示:

https://i.stack.imgur.com/9E56K.png

有什么帮助吗?

我的按钮没有将时间发送到 greenPanel。

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.*;

public class TimePanel {

    public static void main(String[] args) {
        
        Font timeFont = new Font("Helvetica",Font.BOLD,50);
        Font msFont = new Font("Helvetica",Font.PLAIN,72);
        
        Date dateNow = new Date(); // current date and time
        
        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss"); // current time
        SimpleDateFormat msFormat = new SimpleDateFormat(".S"); // milliseconds
        SimpleDateFormat sendToGreenFormat = new SimpleDateFormat("HH:mm:ss.S");
        
        String timeString = timeFormat.format(dateNow);
        String msstring = msFormat.format(dateNow);
        
        JLabel timeLabel = new JLabel(timeString,JLabel.CENTER);
        timeLabel.setFont(timeFont);
        timeLabel.setForeground(new Color(242,242,242));
        timeLabel.setBounds(0,25,240,50);
        
        JLabel msLabel = new JLabel(msstring,JLabel.CENTER);
        msLabel.setFont(msFont);
        msLabel.setForeground(new Color(242,242));
        msLabel.setBounds(0,65);
        
        JButton sendButton = new JButton("Send to Green");
        sendButton.setBounds(585,260,150,25);
        
        JFrame frame = new JFrame("Time Panel");
        frame.setLayout(null);
        
        JPanel greenPanel = new JPanel();
        greenPanel.setLayout(new GridLayout(10,1));
        greenPanel.setBackground(new Color(18,64,55,255));
        greenPanel.setBounds(20,20,500,500);
        
        JPanel timePanel = new JPanel();
        timePanel.setLayout(null);
        timePanel.setBackground(new Color(89,21,33,255));
        timePanel.setBounds(540,100);
        
        JPanel msPanel = new JPanel(); // milliseconds panel.
        msPanel.setLayout(null);
        msPanel.setBackground(new Color(38,7,15,255));
        msPanel.setBounds(540,140,100);
        
        sendButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                
                String timetoGreenString = sendToGreenFormat.format(dateNow);
                
                JLabel timetoGreenLabel = new JLabel(timetoGreenString);
                timetoGreenLabel.setFont(timeFont);
                timetoGreenLabel.setForeground(new Color(242,242));
                timetoGreenLabel.setBounds(0,50);
                
                greenPanel.add(timetoGreenLabel);
            }
        });
                
        timePanel.add(timeLabel);
        msPanel.add(msLabel);
        
        frame.add(greenPanel);
        frame.add(timePanel);
        frame.add(msPanel);
        frame.add(sendButton);
        
        frame.setSize(800,600);
        frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeto(null);
        frame.setVisible(true);

    }

}

解决方法

这是我想出的图形用户界面。

Time Panel GUI

当我创建 Swing GUI 或大多数其他 Java 应用程序时,我使用 model / view / controller 模式。简而言之,这种使用 Swing 的模式意味着:

  1. 视图(Swing 组件)将从模型中读取。

  2. 视图不会改变模型中的任何内容。

  3. 控制器将更新模型并更新视图。

我使用一个或多个普通 Java getter / setter 类创建了一个应用程序模型。我使用 Swing 组件和 Swing layout managers 创建了一个视图。最后,我使用 Swing listeners 创建了一个或多个控制器。控制器似乎是您最难以理解的地方。

以下是我希望您从我将发布的代码中删除的最重要的几点。

  1. 始终通过调用 SwingUtilities invokeLater 方法来启动 Swing 应用程序。此方法可确保您的 Swing 组件将在 Event Dispatch Thread 上创建和执行。

  2. 摆脱静态代码并将您的代码分组到 Java 方法中。您可以在我的代码中看到,唯一的静态方法是启动应用程序的 main 方法。我的主要方法只有一行代码。应用程序的其余部分使用方法和类。

  3. 不要使用绝对定位(setBounds)。使用Swing layout managers。您可以在我的代码中看到 Swing 布局管理器的示例。

  4. 为一个 JFrame 创建多个 JPanel。在单独的方法中创建每个主 JPanel。这允许您在应用程序中组合 Swing 布局管理器。

  5. 在这个特定的应用程序中,控制器非常简单,我将它们设为匿名类。我创建了两个匿名类,一个用于更新左侧的时间面板,另一个用于运行控制面板中的两个时钟。控制器应该始终是与您的模型和视图分开的类。

下次您发布问题时,我不想在 main 方法中看到您的所有代码。我不想看到绝对定位。我希望您花时间学习我在本答案中概述的概念,否则您将永远无法创建复杂的 Swing 应用程序。最后,您应该阅读 Oracle 的完整 Swing tutorial。您可以跳过 Netbeans 部分。

这是代码。我没有费心将时间集中在左侧的时间面板中。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
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.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class TimePanel implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new TimePanel());
    }
    
    private JLabel timeLabel;
    private JLabel msLabel;
    
    private JTextArea textArea;
    
    private TimeModel model;
    
    public TimePanel() {
        this.model = new TimeModel();
    }
    
    @Override
    public void run() {
        JFrame frame = new JFrame("Time Panel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(createTextPanel(),BorderLayout.CENTER);
        frame.add(createControlPanel(),BorderLayout.AFTER_LINE_ENDS);
        
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        
        Timer timer = new Timer(50,new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                updateControlPanel();
            }
        });
        timer.start();
    }   
    
    private JPanel createTextPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5,5,5));
        
        JPanel innerPanel = new JPanel(new BorderLayout());
        innerPanel.setBackground(model.getBackgroundTextColor());
        innerPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10));
        
        textArea = new JTextArea(8,10);
        textArea.setBackground(model.getBackgroundTextColor());
        textArea.setForeground(model.getForegroundColor());
        textArea.setFont(model.getTimeFont());
        innerPanel.add(textArea,BorderLayout.CENTER);
        
        JScrollPane scrollPane = new JScrollPane(innerPanel);
        panel.add(scrollPane);
        return panel;
    }   

    private JPanel createControlPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5,5));
        
        JPanel innerPanel = new JPanel(new GridBagLayout());
        
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.CENTER;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(0,5);
        gbc.gridx = 0;
        gbc.gridy = 0;
        
        JPanel timePanel = new JPanel(new BorderLayout());
        timePanel.setBorder(BorderFactory.createEmptyBorder(5,10));
        timePanel.setBackground(model.getBackgroundControlColor());
        
        timeLabel = new JLabel(model.getTime());
        timeLabel.setBackground(model.getBackgroundControlColor());
        timeLabel.setFont(model.getTimeFont());
        timeLabel.setForeground(model.getForegroundColor());
        timePanel.add(timeLabel,BorderLayout.CENTER);

        JPanel msPanel = new JPanel();
        msPanel.setBackground(model.getBackgroundControlColor());
        
        msLabel = new JLabel(model.getMSTime());
        msLabel.setBackground(model.getBackgroundControlColor());
        msLabel.setFont(model.getMSFont());
        msLabel.setForeground(model.getForegroundColor());
        msPanel.add(msLabel);
        
        Dimension t = timePanel.getPreferredSize();
        Dimension m = msPanel.getPreferredSize();
        int width = Math.max(t.width,m.width);
        int height = Math.max(t.height,m.height);
        Dimension a = new Dimension(width,height);
        
        timePanel.setPreferredSize(a);
        msPanel.setPreferredSize(a);
        
        innerPanel.add(timePanel,gbc);
        
        gbc.gridy++;
        innerPanel.add(msPanel,gbc);

        gbc.gridy++;
        JButton sendButton = new JButton("Send to Green");
        sendButton.setFont(model.getButtonFont());
        innerPanel.add(sendButton,gbc);
        
        sendButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                textArea.append(model.getDisplayTime());
                textArea.append(System.lineSeparator());
            }
        });
        
        panel.add(innerPanel);
                    
        return panel;
    }
    
    public void updateControlPanel() {
        timeLabel.setText(model.getTime());
        msLabel.setText(model.getMSTime());
    }
    
    public class TimeModel {
        
        private final Color foregroundColor;
        private final Color backgroundTextColor;
        private final Color backgroundControlColor;
        
        private final DateTimeFormatter timeFormat;
        private final DateTimeFormatter msFormat;
        private final DateTimeFormatter displayFormat;
        
        private final Font timeFont;
        private final Font msFont;
        private final Font buttonFont;
        
        public TimeModel() {
            this.foregroundColor = new Color(242,242,242);
            this.backgroundTextColor = new Color(18,64,55);
            this.backgroundControlColor = new Color(89,21,33);
            
            this.timeFormat = DateTimeFormatter.ofPattern("HH:mm:ss");
            this.msFormat = DateTimeFormatter.ofPattern(".SSS");
            this.displayFormat = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
            
            String fontName = "Helvetica";
            this.msFont = new Font(fontName,Font.PLAIN,72);
            this.timeFont = new Font(fontName,Font.BOLD,48);
            this.buttonFont = new Font(fontName,16);   
        }
        
        public String getTime() {
            return timeFormat.format(getCurrentTime());
        }
        
        public String getMSTime() {
            return msFormat.format(getCurrentTime());
        }
        
        public String getDisplayTime() {
            return displayFormat.format(getCurrentTime());
        }
        
        public Color getForegroundColor() {
            return foregroundColor;
        }

        public Color getBackgroundTextColor() {
            return backgroundTextColor;
        }

        public Color getBackgroundControlColor() {
            return backgroundControlColor;
        }

        public Font getTimeFont() {
            return timeFont;
        }

        public Font getMSFont() {
            return msFont;
        }

        public Font getButtonFont() {
            return buttonFont;
        }

        private LocalDateTime getCurrentTime() {
            return LocalDateTime.now();
        }
        
    }

}