GUI 问题中图形顶部的 Java 按钮

标签 java swing button user-interface graphics

对于我的年终项目,我正在尝试制作一个游戏来帮助人们研究不同的问题,这些问题显示在 GUI 中。理想情况下,用户可以按下按钮来查看他们的答案是否正确。我已经用变量 ArrayList <String[]> 奠定了 GUI 的基础。变量将保存问题及其答案,并尝试制作按钮。

但是,当我尝试运行该程序时,按钮(显示的代码中只有一个)被切断,我无法将它们放置在正确的位置。请帮忙!

请有人告诉我一个实际上已经过测试并且有效的解决方案!根据到目前为止为我发布的内容,我似乎无法得到它!

enter image description here

这是我运行它时的样子:

这是该程序的所有代码:

import java.awt.*;
import javax.swing.*;
import java.awt.geom.Line2D;
import java.util.*;
import java.awt.event.*;

public class EuroGUI extends JPanel {
    //Instantiate necessary variables.
    ArrayList <String[]> questions = new ArrayList <String[]>();  //Stores (Question + Answers, Correct Answer)

    int width = 1280;   //GUI Size
    int height = 720;   // ^
    int correct = 0;    //Number of correct answers
    int attempted = 0;  //Number of questions attempted
    int streak = 0;     //Number of correct answers in a row
    int points = 0;     //Points accumulated
    Font title = new Font("Serif", Font.PLAIN, 60);
    Font statsTitle = new Font("Serif", Font.PLAIN, 45);
    Font sig = new Font("Mistral", Font.PLAIN, 45);

    //Drop down options stuff
    JMenu ddMenu = new JMenu("Select an option");
    String[] dropDown = new String[] {"A", "B", "C", "D", "E"};

    String completion = "starting"; //Determines if the first time repainting

    Scanner keyboard = new Scanner(System.in);  //Make a keyboard object to test stuff

    public static void main(String[]args){  //Main Runner
        EuroGUI g = new EuroGUI();
        g.setUpScreen();
        g.repaint();
    }

    public void setUpScreen() {  //Create the physical GUI, which paints all graphics
                                 //Used http://www.mathcs.emory.edu/~cheung/Courses/377/Syllabus/8-JDBC/GUI/Progs/Layout1.java for buttons

        //Create actual GUI window and graphics.
        //Create actual GUI window and graphics.
    JFrame f = new JFrame("AP European History Study Tool");

    JPanel panelGrid = new JPanel();
    panelGrid.setLayout(new GridLayout());
    setLayout(null);

    JPanel panelBorder = new JPanel();
    panelBorder.setLayout(new BorderLayout());
    JButton xA = new JButton("Choice A");
    panelGrid.add(xA, "West");

    panelBorder.setLocation(500,500);
    f.getContentPane().add(panelBorder);
    f.setResizable(false);
    f.setVisible(true);
    f.setSize(width, height);
    f.setBackground(Color.lightGray);
    f.add(this);

    }
    public void paintComponent(Graphics g) {  //Draws information on the GUI  (Found information on graphics 2D at http://www.tutorialspoint.com/javaexamples/gui_line.htm)
        Graphics2D g2 = (Graphics2D) (g);

        //Draw a background box which will cover anything that was not re-painted over.
        g.setColor(Color.lightGray);
        g.fillRect (0, 1280, 0, 720);

        //Title "interface"
            //Change color back for the lines;
            g.setColor(Color.blue);
            //Enable bolder lines.
            g2.setStroke(new BasicStroke(6));

            //Create a box of lines around the title.
            g2.draw(new Line2D.Double(200, 0, 200, 120));
            g2.draw(new Line2D.Double(200, 120, 1070, 120));
            g2.draw(new Line2D.Double(1070, 0, 1070, 120));
            g2.draw(new Line2D.Double(200, 0, 1070, 0));

            //Fill in box with title with some colors :)
            g.setColor(Color.green);
            g.fillRect (200, 0, 870, 120);

            //Write title
            g2.setFont(title);
            g.setColor(Color.cyan);
            g.drawString("AP European History Study Tool", 240, 80);
            g.setColor(Color.black);
            g.drawString("AP European History Study Tool", 238, 78);

        //Signiature on Title
            g.setColor(Color.white);
            g2.setFont(sig);
            g.drawString("by My Name", 600, 120);
            g.setColor(Color.blue);
            g.drawString("by My Name", 598, 118);

        //Statistics Bar Outline
            g.setColor(Color.blue);
            g2.draw(new Line2D.Double(1000, 170, 1000, 670));
            g2.draw(new Line2D.Double(1000, 170, 1280, 170));
            g2.draw(new Line2D.Double(1280, 170, 1280, 670));
            g2.draw(new Line2D.Double(1000, 670, 1280, 670));
            g2.setStroke(new BasicStroke(6));
            g.setColor(Color.black);
            g.fillRect (1000, 170, 1280, 500);
            g.setColor(Color.green); //Underline
            g2.setStroke(new BasicStroke(2));
            g2.draw(new Line2D.Double(1055, 230, 1215, 230));
            g2.setStroke(new BasicStroke(6));

        //Overall Score
            g2.setFont(statsTitle);
            g2.setColor(Color.green);
            g.drawString("Statistics", 1055, 220);
            g2.setColor(Color.cyan);
            g.drawString(correct + "/" + attempted + " Correct", 1035, 285); 

        //Streak
            if (streak >= 3)
            {
                g2.setColor(Color.red);
                g.drawString(streak + " Streak", 1060, 340);
            }
            else{
                g2.setColor(Color.cyan);
                g.drawString(streak + " Streak", 1060, 340);
            }


        if (completion.equals("starting")){

        }
    }
}

最佳答案

这是破坏油漆链的症状。

Graphics 是共享资源,即使用同一个 Graphics 上下文来绘制一个绘制周期内的所有组件。

paintComponent 的工作之一是在绘制任何内容之前清除它,从而准备用于绘制的 Graphics 上下文。

所以而不是...

public void paintComponent(Graphics g) {  //Draws information on the GUI  (Found information on graphics 2D at http://www.tutorialspoint.com/javaexamples/gui_line.htm)
    Graphics2D g2 = (Graphics2D) (g);

尝试使用

public void paintComponent(Graphics g) {  //Draws information on the GUI  (Found information on graphics 2D at http://www.tutorialspoint.com/javaexamples/gui_line.htm)
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) (g);

像素完美布局在现代用户界面中是一种幻想。您无法控制字体规范、dpi 或渲染管道等因素,这些因素都会影响各个组件可能需要的空间量。相反,您应该使用适当的布局管理器并考虑使用复合布局来生成更复杂的解决方案

已更新示例

有很多问题,主要问题是,panelGrid 没有添加到任何内容中。 null 布局管理器也没有帮助。

您还将所有精力集中在一个面板上,这将使生活变得一团糟。

相反,尝试将每个部分分成自己的组件并专注于各个需求,从长远来看,您会发现管理起来更容易。

enter image description here

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.MatteBorder;

public class Example {
    public static void main(String[] args) {
        new Example();
    }

    public Example() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new HeaderPane(), BorderLayout.NORTH);
                frame.add(new StatisticsPane(), BorderLayout.EAST);
                frame.add(new QuestionPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class HeaderPane extends JPanel {

        public HeaderPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 1;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.SOUTH;
//            gbc.ipadx = 100;
            NamePane namePane = new NamePane();
            FontMetrics fm = namePane.getFontMetrics(namePane.getFont());
            add(namePane, gbc);

            gbc.insets = new Insets(0, 0, fm.getDescent(), 0);

            gbc.gridx = 0;
            gbc.gridwidth = 2;
            gbc.ipadx = 10;
            gbc.ipady = 10;
            gbc.anchor = GridBagConstraints.CENTER;
            add(new TitlePane(), gbc);
        }

        public class ShadowLabel extends JPanel {

            private String text;
            private Color shadowColor;
            private int shadowOffset;

            public ShadowLabel(String text, Color shadowColor) {
                this.text = text;
                this.shadowColor = shadowColor;
                this.shadowOffset = 2;
            }



            public int getShadowOffset() {
                return shadowOffset;
            }

            public void setShadowOffset(int shadowOffset) {
                this.shadowOffset = shadowOffset;
            }

            @Override
            public Dimension getPreferredSize() {
                FontMetrics fm = getFontMetrics(getFont());
                return new Dimension(fm.stringWidth(getText()), fm.getHeight());
            }

            public String getText() {
                return text;
            }

            public Color getShadowColor() {
                return shadowColor;
            }

            public void setText(String text) {
                this.text = text;
                repaint();
            }

            public void setShadowColor(Color shadowColor) {
                this.shadowColor = shadowColor;
                repaint();
            }

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setFont(getFont());
                FontMetrics fm = g.getFontMetrics();
                int x = (getWidth() - fm.stringWidth(getText())) / 2;
                int y = (getHeight() - fm.getHeight()) / 2;
                g.setColor(getShadowColor());
                g.drawString(getText(), x + getShadowOffset(), y + getShadowOffset() + fm.getAscent());
                g.setColor(getForeground());
                g.drawString(getText(), x, y + fm.getAscent());
            }


        }

        public class TitlePane extends ShadowLabel {

            public TitlePane() {
                super("AP European History Study Tool", Color.CYAN);
                setBackground(Color.GREEN);
                setBorder(new MatteBorder(0, 1, 1, 1, Color.BLUE));
                setFont(new Font("Serif", Font.PLAIN, 60));
            }

        }

        public class NamePane extends ShadowLabel {

            public NamePane() {
                super("by Me", Color.WHITE);
                setForeground(Color.BLUE);
                setFont(new Font("Mistral", Font.PLAIN, 45));
                setOpaque(false);
            }

        }

    }

    public class StatisticsPane extends JPanel {

        private JLabel score;
        private JLabel streak;

        public StatisticsPane() {
            setLayout(new BorderLayout());
            setBackground(Color.BLACK);
            setBorder(new CompoundBorder(new LineBorder(Color.BLUE), new EmptyBorder(4, 4, 4, 4)));

            JLabel statistics = new JLabel("Statistics");
            statistics.setFont(new Font("Serif", Font.PLAIN, 45));
            statistics.setForeground(Color.GREEN);
            statistics.setBorder(new CompoundBorder(new MatteBorder(0, 0, 1, 0, Color.GREEN), new EmptyBorder(4, 4, 4, 4)));
            add(statistics, BorderLayout.NORTH);

            score = new JLabel("0/0 correct");
            score.setForeground(Color.GREEN);
            score.setFont(new Font("Serif", Font.PLAIN, 45));
            streak = new JLabel("0 streak");
            streak.setForeground(Color.GREEN);
            streak.setFont(new Font("Serif", Font.PLAIN, 45));

            JPanel pnl = new JPanel(new GridBagLayout());
            pnl.setOpaque(false);
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            pnl.add(score, gbc);
            gbc.gridy++;
            gbc.weighty = 1;
            gbc.anchor = GridBagConstraints.NORTH;
            pnl.add(streak, gbc);

            add(pnl);

        }

    }

    public class QuestionPane extends JPanel {

        public QuestionPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.anchor = GridBagConstraints.WEST;
            JButton xA = new JButton("Choice A");
            add(xA, gbc);
        }

    }
}

我还将数据和 UI 的管理分开,以便数据由某种或多个可以响应 UI 变化的模型来管理,反之亦然。这意味着您的 UI 成为数据模型的可视化表示,并允许两者解耦并彼此独立工作...

看看Model–view–controller更多细节。注意:Swing 使用了此版本的一个版本,但它更像是模型 View 和 Controller

您还应该看看Creating a GUI With JFC/Swing了解如何更好地利用 Swing 中提供的现成组件

关于GUI 问题中图形顶部的 Java 按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23440713/

相关文章:

java - 改进通过套接字从桌面到 Android 服务的数据传输

java - JTextArea 获取整行

Java swing 键绑定(bind)

java - 绕过 java.awt.Container.createHierarchyEvents 中的 IndexOutOfBoundsException

CSS:我不能将按钮放在 DIV 元素的中间

jquery - 将按钮附加到可折叠内容中

java - 生成外部编辑器 - 这是如何工作的?

java - 如何创建一个平铺 map (我只是得到一个白屏)

java - 如何让 Glide 与 Android Studio 3.0 配合使用?

javascript - 将 onclick 处理程序设置为动态创建的按钮