«Плавающий» JToolBarJAVA

Программисты JAVA общаются здесь
Anonymous
«Плавающий» JToolBar

Сообщение Anonymous »

Моя цель: создать панель инструментов с кнопками, которые «стекают» вниз, когда окно сжимается достаточно сильно. При необходимости не следует стесняться подталкивать брата или сестру, расположенного ниже.
Как мне это сделать?
Вот демо . Я ответил на некоторые критические замечания по поводу моих предыдущих вопросов об использовании внешних библиотек, поэтому здесь они не используются

Код: Выделить всё

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.Objects;

public class FlowToolbarDemo {
public static void main(String[] args) throws IOException {
JFrame frame = new JFrame("Flow Toolbar Demo");
JPanel labelPanel = new JPanel(new BorderLayout());
JLabel label = new JLabel("Click to see action");
label.setOpaque(true);
label.setBackground(new Color(255, 255, 204));
labelPanel.add(label, BorderLayout.CENTER);

JToolBar toolbar = new JToolBar();
LayoutManager toolbarLayout = new FlowLayout();
toolbar.setLayout(toolbarLayout);
JButton heartButton = getHeartButton(e -> label.setText("Heart action performed..."));
JButton starButton = getStarButton(e ->  label.setText("Star action performed..."));
toolbar.add(heartButton);
toolbar.add(starButton);

LayoutManager headerPanelLayout = new BorderLayout();
JPanel headerPanel = new JPanel(headerPanelLayout);
headerPanel.add(labelPanel, BorderLayout.NORTH);
headerPanel.add(toolbar, BorderLayout.CENTER);

JPanel businessPanel = getBusinessPanel();

LayoutManager mainPanelLayout = new BorderLayout();
JPanel mainPanel = new JPanel(mainPanelLayout);
mainPanel.add(headerPanel, BorderLayout.NORTH);
mainPanel.add(businessPanel, BorderLayout.CENTER);

frame.setContentPane(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
System.out.println();
}

private static JPanel getBusinessPanel() {
LayoutManager businessPanelLayout = new BorderLayout();
JPanel businessPanel = new JPanel(businessPanelLayout);
JTable tableOne = getTableOne();
JScrollPane scrollPaneOne = new JScrollPane(tableOne);
scrollPaneOne.setOpaque(true);
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("Business Table One", scrollPaneOne);
JTable tableTwo = getTableTwo();
JScrollPane scrollPaneTwo = new JScrollPane(tableTwo);
scrollPaneTwo.setOpaque(true);
tabbedPane.addTab("Business Table Two", scrollPaneTwo);
businessPanel.add(tabbedPane);
return businessPanel;
}

private static JTable getTableOne() {
Object[][] data = {
{"John Doe", 30, "Male"},
{"Jane Smith", 25, "Female"},
{"Alice Johnson", 35, "Female"}
};
String[] columns = {"Name", "Age", "Gender"};
DefaultTableModel model = new DefaultTableModel(data, columns);
return new JTable(model);
}

private static JTable getTableTwo() {
Object[][] data = {
{"Apple", 30, true},
{"Orange", 25, true},
{"Ackee fruit", 35, false}
};
String[] columns = {"Fruit", "Quantity", "Is Edible"};
DefaultTableModel model = new DefaultTableModel(data, columns);
return new JTable(model);
}

private static JButton getHeartButton(ActionListener heartAction) throws IOException {
return getButton("Do Heart action", "heart.png", heartAction);
}
private static JButton getStarButton(ActionListener starAction) throws IOException {
return getButton("Do Star action", "star.png", starAction);
}

private static JButton getButton(String buttonText, String resourceName, ActionListener actionListener) throws IOException {
URL imageLocation = FlowToolbarDemo.class.getResource(resourceName);
BufferedImage image = ImageIO.read(Objects.requireNonNull(imageLocation, "Requested resource not found"));
Image scaledImage = image.getScaledInstance(20, 20, Image.SCALE_SMOOTH);
ImageIcon icon = new ImageIcon(scaledImage);
JButton button = new JButton(buttonText, icon);
button.addActionListener(actionListener);
button.setFocusPainted(false);
return button;
}
}

Код: Выделить всё

heart.png
Изображение

Код: Выделить всё

star.png
Изображение

Кнопки перемещаются, но они располагаются ниже выделенной области для северного компонента и становятся практически невидимыми. С другой стороны, заголовки панелей JTabbedPane плавно перетекают. Я включил его частично, чтобы показать, какого типа «плавности» я пытаюсь добиться с помощью кнопок на панели инструментов.
[img]https:/ /i.sstatic.net/gYUheBPI.png[/img]

Изображение

Код: Выделить всё

BorderLayout
выбран для главной панели, поскольку он известен тем, что соблюдает предпочтительную высоту своих северных компонентов (в данном случае это панель заголовка). Однако, как я обнаружил с помощью отладчика IntelliJ, предпочтительная высота панели заголовка не меняется даже после сложения кнопок. Это потому, что предпочтительная высота панели инструментов не меняется. Если бы это было так, мы бы получили что-то вроде этого
Изображение

Технически это достижимо с помощью такого уродливого ключа

Код: Выделить всё

        toolbar.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
Component firstButton = toolbar.getComponent(0);
double firstButtonY = firstButton.getLocation().getY();
Component secondButton = toolbar.getComponent(1);
double secondButtonY = secondButton.getLocation().getY();
if (firstButtonY < secondButtonY) {
int newHeight = (int) ((firstButton.getHeight() + secondButton.getHeight()) * 1.25);
toolbar.setPreferredSize(new Dimension(toolbar.getPreferredSize().width, newHeight));
} else if (firstButtonY == firstButtonY) {
int oldHeight = (int) (firstButton.getHeight() * 1.25);
toolbar.setPreferredSize(new Dimension(toolbar.getPreferredSize().width, oldHeight));
}
}
});
но, очевидно, я не хочу его продвигать
Даже если несколько улучшить его, заменив жестко закодированные множители на средства доступа vGap
p>

Код: Выделить всё

        toolbar.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
FlowLayout flowLayout = (FlowLayout) toolbar.getLayout();
JButton firstButton = (JButton) toolbar.getComponent(0);
JButton secondButton = (JButton) toolbar.getComponent(1);
double firstButtonY = firstButton.getLocation().getY();
double secondButtonY = secondButton.getLocation().getY();
if (firstButtonY < secondButtonY) {
int newHeight = firstButton.getHeight() + secondButton.getHeight() + flowLayout.getVgap() * 3;
toolbar.setPreferredSize(new Dimension(toolbar.getPreferredSize().width, newHeight));
} else if (firstButtonY == firstButtonY) {
int oldHeight = firstButton.getHeight() + flowLayout.getVgap() * 2;
toolbar.setPreferredSize(new Dimension(toolbar.getPreferredSize().width, oldHeight));
}
}
});
еще остается проблема: он не поддерживает более двух кнопок. Опять же, я могу написать какой-нибудь цикл, но он окажется слишком сложным для чего-то, что, скорее всего, доступно OOB


Подробнее здесь: https://stackoverflow.com/questions/787 ... g-jtoolbar

Вернуться в «JAVA»