Не могу заставить кнопки быть в центре правильного положения - PullRequest
0 голосов
/ 11 мая 2018

Я пытаюсь понять, как расположить мои кнопки в правильном центральном положении.Я добавил то, что я сделал до сих пор, и я добавлю рисунок того, как я хочу, чтобы он был.

Я пытаюсь понять, как определить позицию, которую я хочу в Swing, не могу понятьПреимущества каждого макета.

Мой код пока:

package Game;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.Timer;


public class MainWindow extends JFrame implements ActionListener {

    private JButton exit;
    private JButton start_Game;
    private ImageIcon puzzleBackground;
//  private JLabel back_Label;
//  private GridBagConstraints grid = new GridBagConstraints();
    private JPanel menu;

    public MainWindow() 
    {
        super("Welcome");
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setSize(450,300);
        setLocationRelativeTo(null);
        this.setLayout(new FlowLayout(FlowLayout.RIGHT));
        menu = new JPanel();
        menu.setLayout(new BorderLayout());
        //setResizable(false);

        //===== Background =====
        puzzleBackground = new ImageIcon("MyBackground.jpg");
        setContentPane(new JLabel(puzzleBackground));

        exit = new JButton("Exit");
        menu.add(exit, BorderLayout.CENTER);
        exit.addActionListener(this);

        start_Game = new JButton("Start to play");
        menu.add(start_Game, BorderLayout.SOUTH);
        exit.addActionListener(this);
        start_Game.addActionListener(this);

//      
//      back_Label = new JLabel(puzzleBackground);
//      back_Label.setLayout(new BorderLayout());

        //===== Buttons =====
//      back_Label.add(exit,BorderLayout.CENTER);
//      
//      back_Label.add(start_Game,BorderLayout.EAST);
//      
        add(menu);
        setVisible(true);
    }


    public static void main(String args[])
    {
        MainWindow a = new MainWindow();
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == exit)
        {
            System.exit(0);
        }
        else
        {
            //open start up window.
        }

    }

}

image

Ответы [ 3 ]

0 голосов
/ 11 мая 2018

Делать пользовательский интерфейс в Java не рекомендуется, но игнорировать это.

Вы получаете (рассчитываете) высоту и ширину экрана.Затем начните рисовать кнопки в зависимости от этого.Рисование кнопки на экранах 50% ширины значения пикселя и 50% значения высоты пикселя приведет к центрированию кнопки.

Просто создайте кнопки с переменным положением, которое рассчитывается по размеру основного экрана в пикселях, и размещайте их там, где вы когда-либохочу.

0 голосов
/ 11 мая 2018

Лучший способ добавить изображение BG - использовать пользовательский нарисованный JPanel.Затем установите макет панели и добавьте в нее другие панели или компоненты.Обратите внимание, что здесь кнопки в основном не отображаются , потому что они добавляются к JLabel.

. Здесь представлен альтернативный вариант, работающий в том же направлении, при этом красная панель является панелью.который настраивает закрашивание фонового изображения и прозрачной панели menu (ищите метод opaque).

enter image description here

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

public class MainWindow extends JFrame {

    private JPanel menu;
    private JPanel contentPane = new JPanel(new BorderLayout(4,4));

    public MainWindow() {
        super("Welcome");
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        //setSize(450, 300); // use pack() instead
        setContentPane(contentPane);
        contentPane.setBorder(new EmptyBorder(8,8,8,8));
        contentPane.setBackground(Color.RED);
        contentPane.add(new JLabel(new ImageIcon(
                new BufferedImage(400,200,BufferedImage.TYPE_INT_RGB))));

        menu = new JPanel(new GridLayout(0,1,10,10));

        menu.add(new JButton("Exit"), BorderLayout.CENTER);
        menu.add(new JButton("Start to play"), BorderLayout.SOUTH);

        JPanel menuCenterPanel = new JPanel(new GridBagLayout());
        menuCenterPanel.add(menu);
        add(menuCenterPanel, BorderLayout.LINE_END);

        pack();
        setLocationRelativeTo(null); // do AFTER pack()
        setMinimumSize(getSize());
        setVisible(true);
    }

    public static void main(String args[]) {
        MainWindow a = new MainWindow();
    }
}
0 голосов
/ 11 мая 2018

Итак, ваша основная проблема сводится к следующим строкам ...

this.setLayout(new BorderLayout());
//...

//===== Background =====
puzzleBackground = new ImageIcon("MyBackground.jpg");
setContentPane(new JLabel(puzzleBackground));

Можете ли вы сказать мне, что на самом деле используется менеджер компоновки? Неправильно. Диспетчер макетов теперь null, потому что JLabel на самом деле не имеет диспетчера по умолчанию.

Таким образом, «простой» ответ будет состоять в том, чтобы переместить вызов setLayout ниже уровня вызова setContentPane, но это будет недальновидный ответ, так как JLabel вычисляет его предпочтение на основе значка и свойств текста только не дочерние компоненты.

Лучшим решением было бы сделать что-то, продемонстрированное в Как установить фоновое изображение в JPanel (см. Второй пример)

Это означает, что если изображение меньше, чем требуемое пространство, компоненты исчезнут с экрана.

Я прошел и немного почистил код, только с целью заставить работать макет

Simple layout

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MainWindow extends JFrame implements ActionListener {

    private JButton exit;
    private JButton start_Game;
    private JPanel menu;

    public MainWindow() {
        super("Welcome");
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setLocationRelativeTo(null);
        this.setLayout(new BorderLayout());
        menu = new JPanel();
        menu.setLayout(new GridBagLayout());

        exit = new JButton("Exit");
        exit.addActionListener(this);

        start_Game = new JButton("Start to play");
        exit.addActionListener(this);
        start_Game.addActionListener(this);

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.weightx = 1;
        gbc.fill = gbc.HORIZONTAL;
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        menu.add(exit, gbc);
        menu.add(start_Game, gbc);

        // This is just a filler, it can be removed, but it helps prove the point

        add(new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
        });

        add(menu, BorderLayout.EAST);
        pack();
        setVisible(true);
    }

    public static void main(String args[]) {
        MainWindow a = new MainWindow();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == exit) {
            System.exit(0);
        } else {
            //open start up window.
        }

    }

}

Я также хотел бы отметить, что расширение непосредственно от JFrame также недальновидно, оно блокирует вас в одноразовом контейнере, и вы фактически не добавляете в класс никаких новых функциональных возможностей.

Пример лучшей структуры ...

Ниже приведен простой пример, возможно, лучшей структуры. В нем отсутствует понятие «контроллер», который контролирует вещи и «модель», которая поддерживает информацию о состоянии, которая используется пользовательским интерфейсом для отображения «вещей», но дает отправную точку

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Main {

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

    public Main() {
        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("Welcome");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new MainPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MainPane extends JPanel {

        public MainPane() {
            setLayout(new BorderLayout());
            // This is just a filler, it can be removed, but it helps prove the point
            add(new JPanel() {
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(200, 200);
                }
            });

            add(new MenuPane(), BorderLayout.EAST);
        }

    }

    public class MenuPane extends JPanel {

        private JButton exit;
        private JButton start_Game;
        private JPanel menu;

        public MenuPane() {
            menu = new JPanel();
            menu.setLayout(new GridBagLayout());

            ActionHandler actionHandler = new ActionHandler();

            exit = new JButton("Exit");
            exit.addActionListener(actionHandler);

            start_Game = new JButton("Start to play");
            start_Game.addActionListener(actionHandler);

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.weightx = 1;
            gbc.fill = gbc.HORIZONTAL;
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            menu.add(exit, gbc);
            menu.add(start_Game, gbc);
        }

        public class ActionHandler implements ActionListener {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (e.getSource() == exit) {
                    System.exit(0);
                } else {
                    //open start up window.
                    // This should be used to notifiy a controller class
                    // that some new action needs to take place, the controller
                    // is then responsible for making it happen
                }
            }

        }

    }

}
...