jsplitpane 和 paintcomponent 相互冲突

jsplitpane and paintcomponent conflicting with each other

我的代码有问题,因为当我将我的城市 class 实例化为一个对象并将其添加到我的 JSplitPane 的右侧(甚至左侧)时,圆圈应该绘制的没有出现。我的城市 class 使用 paintComponent 并且应该通过调用构造函数来绘制一个圆。我也试过将重绘放在它自己的 drawIt() 方法中,但结果仍然相同。按钮和微调器显示在分隔线的左侧,但我尝试绘制的圆圈根本没有显示。

这是我的城市 class。

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

public class City extends JPanel{
    int xPos, yPos;
    
    City(int x, int y){
        xPos = x;
        yPos = y;
        repaint();
    }
    
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        
        g.setColor(Color.BLACK);
        g.fillOval(xPos, yPos, 10, 10);
    }
    
}

这是我的主要内容。 在这里,我尝试实例化我的城市并将其添加到 JSplitPane 的右侧(在“添加组件”下),这就是我遇到问题的地方,因为黑色圆圈不会绘制在 JSplitPane 上。

import java.awt.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;

public class TSP{   
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            
            @Override
            public void run() {
                new TSP();
            }
        });
    }
    
    TSP(){
        JLabel instructions = new JLabel("Enter the number of cities: ");
        instructions.setBounds(30, 150, 300, 40);
        
        SpinnerNumberModel numMod = new SpinnerNumberModel(2, 2, 10, 1);
        JSpinner numOfCities = new JSpinner(numMod);
        numOfCities.setBounds(185, 150, 80, 40);
        
        JButton start = new JButton("Start Simulation");
        start.setBounds(50, 400, 200, 40);
        
        JFrame frame = new JFrame("Travelling Salesperson");
        
        JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
        JPanel lp = new JPanel(null);
        JPanel rp = new JPanel(null);
        sp.setDividerLocation(300);
        sp.setLeftComponent(lp);
        sp.setRightComponent(rp);
        sp.setEnabled(false);
            
        frame.setDefaultCloseOperation(3);
        frame.setSize(1100,600);
        frame.setResizable(false);
        ////////////////Add Components//////////////////////////
        lp.add(instructions);
        lp.add(numOfCities);
        lp.add(start);
        
        City test = new City(301, 301);
        rp.add(test);
        
        frame.add(sp);
        ////////////////////////////////////////////////////////    
        
        frame.setVisible(true);
    }

}

我觉得圆圈是在 JSplitPane 下绘制的,就好像我将我的城市对象(测试)添加到我的框架而不是 JSplitPane(frame.add(测试)而不是 rp.add(测试)在“添加组件”部分下)黑色圆圈将出现在所需位置,但 JSplitPane 以及按钮和微调器将消失,所以我觉得它们似乎存在冲突。有没有解决这个问题的方法,或者是否有另一种方法可以使圆出现在右侧,而其他组件出现在左侧。 我不知道为什么它不在 JSplitPane 上画圆圈,但我们将不胜感激。谢谢! 抱歉,如果有任何不清楚的地方或我的代码中有任何歧义,或者如果我需要 post 更多信息,因为我对 post 还很陌生。让我知道是否还有其他需要添加的内容,或者如果对我的问题有任何疑问!

编辑: 似乎有什么东西挡住了我画圆的地方,就像另一个 JPanel 一样。下面是一张图片。如您所见,圆的一部分看起来好像被覆盖了。我画的小方框是唯一可以看到该点的区域(圆圈的其他任何地方都被白色覆盖)。此外,下图中圆的坐标位于 (3, 0),即 City test = new City(3, 0); 我不太清楚为什么会这样。 the invisible JPanel?

既然我已经看到了你想要做的事情,我可以提供一个更合适的答案。

您在左侧有一个控制面板,在右侧有一个绘图面板。通常,您不使用 JSplitPane 来分隔面板。要创建布局,您可以将控制面板添加到 JFrame BorderLayout 的 LINE_START 并将绘图面板添加到 CENTER。

这样做的原因是您不想不断地重新计算绘图面板的大小。

所以让我向您展示一种获得良好开端的方法。这是我创建的 GUI。

这是我做的事情。

  1. 所有 Swing GUI 应用程序必须以调用 SwingUtilities invokeLater 方法开始。此方法确保在 Event Dispatch Thread.

    上创建和执行 Swing 组件
  2. 我把JFrame、控制面板和绘图面板的创建分开了。这样,我一次可以专注于 GUI 的一部分。

  3. 必须按特定顺序调用 JFrame 方法。这是我在大多数 Swing 应用程序中使用的顺序。

  4. JFrame 未调整大小。它是包装好的。 Swing layout managers 将计算组件的大小和 JPanels.

  5. 我使用了 FlowLayoutGridBagLayout 来创建控制面板。是的,这看起来比绝对定位更复杂,但在长运行 中,布局管理器允许 GUI 更加灵活。

  6. 我在绘图面板中使用了setPreferredSize方法来设置绘图面板的首选尺寸。因为我知道绘图面板的大小,所以我可以把第一个城市放在绘图面板的中央。

这是代码。您不必完全像这样编写代码,但这段代码应该为您开始项目打下良好的基础。查看 model / view / controller pattern 并了解如何进一步将您的代码分成更小的部分,以便您一次专注于应用程序的一部分。

我把所有的类放在一个文件里,方便粘贴。您应该将这些 类 分成单独的文件。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
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.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;

public class CitySimulation implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new CitySimulation());
    }

    private ControlPanel controlPanel;

    private DrawingPanel drawingPanel;

    private JFrame frame;

    @Override
    public void run() {
        frame = new JFrame("Traveling Salesperson");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        controlPanel = new ControlPanel();
        frame.add(controlPanel.getPanel(), BorderLayout.LINE_START);

        drawingPanel = new DrawingPanel();
        frame.add(drawingPanel, BorderLayout.CENTER);

        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public class ControlPanel {

        private JPanel panel;

        public ControlPanel() {
            panel = new JPanel(new FlowLayout());

            JPanel mainPanel = new JPanel(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();

            gbc.anchor = GridBagConstraints.LINE_START;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.insets = new Insets(10, 10, 10, 10);

            JLabel instructions = new JLabel("Enter the number " +
                    "of cities:");
            mainPanel.add(instructions, gbc);

            gbc.gridx++;
            gbc.insets = new Insets(10, 0, 10, 10);

            SpinnerNumberModel numMod =
                    new SpinnerNumberModel(2, 2, 10, 1);
            JSpinner numOfCities = new JSpinner(numMod);
            mainPanel.add(numOfCities, gbc);

            gbc.anchor = GridBagConstraints.CENTER;
            gbc.gridx = 0;
            gbc.gridy++;
            gbc.gridwidth = 2;
            gbc.insets = new Insets(10, 10, 10, 10);

            JButton start = new JButton("Start Simulation");
            mainPanel.add(start, gbc);

            panel.add(mainPanel);
        }

        public JPanel getPanel() {
            return panel;
        }

    }

    public class DrawingPanel extends JPanel {

        private static final long serialVersionUID = 1L;

        public DrawingPanel() {
            this.setBackground(Color.WHITE);
            this.setPreferredSize(new Dimension(400, 400));
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            g.setColor(Color.BLACK);
            g.fillOval(195, 195, 10, 10);
        }
        
    }

}