Я пытаюсь создать дизайн, похожий на строку заголовка браузера (в верхней части браузера). С левой стороны есть вкладки, а с правой стороны есть кнопка минимизировать, изменить размер (свернуть / развернуть), выйти.
Для этого я пробовал вроде.
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.RIGHT));
JPanel tabpanel= new JPanel();
tabpanel.setLayout(new FlowLayout(FlowLayout.LEFT));
tabpanel.add(new JButton("Tab 1"));
tabpanel.add(new JButton("Tab 2"));
panel.add(tabpanel);
panel.add(new JButton("Minimize"));
panel.add(new JButton("Resize"));
panel.add(new JButton("Quit"));
Созданы кнопки «Выйти», «Изменить размер», «Свернуть» справа по мере необходимости, но вкладки созданы рядом с кнопкой «Свернуть», а не СЛЕВА от кадра. Я думаю, что должен быть метод или что-то еще, чтобы заполнить его оставшимся содержимым, или мне следует использовать другой макет? Любая помощь приветствуется
@MadProgrammer Ересь !!!! ;-) (Серьезно, GridBagLayout известен как несколько неудобно использовать). Судя по описанию, это можно решить, поместив BorderLayout в строку заголовка и поместив две панели с кнопками в EAST и WEST. @Tekin Если вы думаете, что это может решить проблему, я бы написал это как ответ, включая минимальный воспроизводимый пример)
При размещении MCVE, предложенного @ Marco13: Предоставьте ASCII-арт или простой рисунок макета предназначены графического интерфейса минимального размера и, если его можно изменить, с большей шириной и высотой, чтобы показать, как следует использовать дополнительное пространство.
@ Marco13 GridBagLayout - самый гибкий из доступных менеджеров компоновки, с ним приходит сложность. Это решило бы проблему, которую OP описывает очень просто, в одном контейнере.
@ Marco13 Готово, решено в 9 строках кода ??
Я решил использовать Gridbaglayout, но проблема в том, что я не могу знать его механизм. После многих исследований я обнаружил, что эта ссылка может быть полезной netbeans.org/kb/docs/java/gbcustomizer-basic.html




Я предлагаю использовать BoxLayout в качестве менеджера компоновки panel для организации левой и правой части.
Полный демонстрационный код ниже:
import javax.swing.*;
import java.awt.*;
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(()->{
JFrame frame = new JFrame("Solution");
JPanel container = new JPanel();
container.setLayout(new BorderLayout());
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
JPanel tabpanel= new JPanel();
tabpanel.setLayout(new FlowLayout(FlowLayout.LEFT));
tabpanel.add(new JButton("Tab 1"));
tabpanel.add(new JButton("Tab 2"));
panel.add(tabpanel);
panel.add(new JButton("Minimize"));
panel.add(new JButton("Resize"));
panel.add(new JButton("Quit"));
container.add(panel, BorderLayout.PAGE_START);
frame.add(container);
frame.pack();
frame.setSize(new Dimension(500,500));
frame.setVisible(true);
});
}
}
На что это похоже:
(1+), но, насколько мне известно, BoxLayout не добавляет автоматически интервалы между компонентами. Когда я запускаю ваш код в Windows, кнопки Minimize / Resize / Quit не имеют интервалов, и вам нужно добавить Box.createHorizontalStrut (5) между компонентами, чтобы получить тот же интервал в 5 пикселей, который вы получаете по умолчанию с FlowLayout. При использовании BoxLayout вам также не нужна tabPanel. Вы просто добавляете кнопки, а затем используете Box.addHorizontalGlue () после второй кнопки вкладки. См. Руководство по Swing на Использование невидимых компонентов в качестве наполнителя.
Как предлагается в комментариях: одним из решений может быть размещение «вкладок» и «кнопок» на отдельных панелях и добавление их в WEST и EAST панели заголовков, на которой есть BorderLayout:
Вот MCVE:
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TitleBarLayout
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui()
{
JFrame f = new JFrame();
JPanel mainPanel = new JPanel(new BorderLayout());
JPanel titleBar = new JPanel(new BorderLayout());
JPanel tabPanel = new JPanel();
tabPanel.setLayout(new FlowLayout());
tabPanel.add(new JButton("Tab 1"));
tabPanel.add(new JButton("Tab 2"));
titleBar.add(tabPanel, BorderLayout.WEST);
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(new JButton("Minimize"));
buttonsPanel.add(new JButton("Resize"));
buttonsPanel.add(new JButton("Quit"));
titleBar.add(buttonsPanel, BorderLayout.EAST);
mainPanel.add(titleBar, BorderLayout.NORTH);
f.getContentPane().add(mainPanel);
f.setSize(800, 600);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
Я очень рекомендую GridBagLayout, это один из самых гибких и настраиваемых менеджеров компоновки, но он приносит с собой сложность.
public class HeaderPane extends JPanel {
public HeaderPane() {
setLayout(new GridBagLayout());
add(new JButton("Tab 1"));
add(new JButton("Tab 2"));
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.anchor = GridBagConstraints.BASELINE_TRAILING;
add(new JButton("Minimize"), gbc);
add(new JButton("Maximise"));
add(new JButton("Close"));
}
}
Аррггх, горит сложность, горит ? сарказм
Итак, это решение представляет собой единый контейнер с одним менеджером компоновки. Я не говорю, что более сложное требование может выиграть от составного решения (у меня возникнет соблазн поместить кнопки min / max / close и tab в собственные контейнеры), но в качестве отправной точки это относительно просто.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(600, 200);
}
});
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class HeaderPane extends JPanel {
public HeaderPane() {
setLayout(new GridBagLayout());
add(new JButton("Tab 1"));
add(new JButton("Tab 2"));
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.anchor = GridBagConstraints.BASELINE_TRAILING;
add(new JButton("Minimize"), gbc);
add(new JButton("Maximise"));
add(new JButton("Close"));
}
}
}
(1+) На этом примере я понял несколько вещей: 1) если вы не укажете ограничения, вы получите «потоковую компоновку» 2) Я не знал, что менеджеры компоновки работают по-разному в Mac и Windows. В этом примере и в примере BoxLayout от Hao в Windows нет промежутков между компонентами. Я думал, что это задача менеджера по расположению - контролировать интервалы. Макинтош каким-то образом отменяет это, чтобы убедиться, что между компонентами есть разрыв? Я бы подумал, что вам нужно использовать ограничение «вставки», чтобы получить промежуток между компонентами.
@camickr, я думаю, дело в том, как работают кнопки - кнопки Mac имеют дополнительные вставки для границы фокуса
@MadProgrammer На самом деле все подходы решили мою проблему, но я решил использовать Gridbaglayout, но я не мог понять, как это сделал Gridbaglayout. GridBagConstraints.BASELINE_TRAILING - это ключ, но я не смог его понять. Есть ли хорошее объяснение, чтобы понять?
@ TekinGüllü Как использовать GridBagLayout было бы хорошим местом для начала. Свойство anchor просто сообщает макету, где в ячейке должны быть размещены компоненты, BASELINE_TRAILING означает, что компонент должен быть размещен горизонтально по заднему краю. "Задняя кромка" имеет разное значение для языков с письмом слева направо и справа налево.
Я просто скажу это -
GridBagLayout