Swingクラスを使用してグリッドUI(5 * 5)を作成しようとしています。ネストされたループを試し、jPanelをjFrameに動的に追加しました。また、ユーザーがクリックしてドロップしたときの各jPanelの背景色を変更しようとしました。しかし、私のコードでは、各セル間に大きなギャップがあり、ドラッグイベントを機能させることができません。
public class clsCanvasPanel extends JPanel {
private static final int intRows = 5;
private static final int intCols = 5;
private List<JPanel> jpllist = new ArrayList<JPanel>();
public clsCanvasPanel() {
/*
*
* Add eventListener to individual JPanel within CanvasPanel
*
*
* TODO :
* 1) mousePressed --> update Temperature and HeatConstant of clsElement Class
* 2) start a new thread and
* 3) call clsElement.run() method
*
*
* Right Now : it updates the colours of the JPanel
* */
MouseListener mouseListener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
JPanel panel = (JPanel) e.getSource();
Component[] components = panel.getComponents();
for (Component component : components) {
component.setVisible(!component.isVisible());
component.setBackground(new Color(255,255,0));
}
panel.revalidate();
panel.repaint();
}
};
//TODO : refactoring
GridLayout gdlyPlates = new GridLayout();
gdlyPlates.setColumns(intCols);
gdlyPlates.setRows(intRows);
gdlyPlates.setHgap(0);
gdlyPlates.setVgap(0);
setLayout(gdlyPlates);
//TODO : refactoring
for (int row = 0; row < intRows; row++) {
for (int col = 0; col < intCols; col++) {
JPanel panel = new JPanel(new GridBagLayout());
panel.setOpaque(false);
JPanel jl = new JPanel();
jl.setVisible(true);
panel.add(jl);
panel.addMouseListener(mouseListener);
jpllist.add(panel);
add(panel);
}
}
}
}
そこで、1つのパネルを作成してその上にグリッドを描画し、グリッド上のマウスの位置を検出して、各セルの色をさらに変更しようとしています。
このグリッドをJPanelに実装し、選択したセルの色を変更する方法について、誰かにアドバイスをいただけませんか。
何を達成したいかに応じて、これを機能させる方法はいくつもあります。
この最初の例では、2D Graphics APIを使用してセルをレンダリングし、MouseMotionListener
を使用してどのセルが強調表示されているかを監視します。
import Java.awt.BorderLayout;
import Java.awt.Color;
import Java.awt.Dimension;
import Java.awt.EventQueue;
import Java.awt.Graphics;
import Java.awt.Graphics2D;
import Java.awt.Point;
import Java.awt.Rectangle;
import Java.awt.event.MouseAdapter;
import Java.awt.event.MouseEvent;
import Java.util.ArrayList;
import Java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestGrid01 {
public static void main(String[] args) {
new TestGrid01();
}
public TestGrid01() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int columnCount = 5;
private int rowCount = 5;
private List<Rectangle> cells;
private Point selectedCell;
public TestPane() {
cells = new ArrayList<>(columnCount * rowCount);
MouseAdapter mouseHandler;
mouseHandler = new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
Point point = e.getPoint();
int width = getWidth();
int height = getHeight();
int cellWidth = width / columnCount;
int cellHeight = height / rowCount;
selectedCell = null;
if (e.getX() >= xOffset && e.getY() >= yOffset) {
int column = (e.getX() - xOffset) / cellWidth;
int row = (e.getY() - yOffset) / cellHeight;
if (column >= 0 && row >= 0 && column < columnCount && row < rowCount) {
selectedCell = new Point(column, row);
}
}
repaint();
}
};
addMouseMotionListener(mouseHandler);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
public void invalidate() {
cells.clear();
selectedCell = null;
super.invalidate();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth();
int height = getHeight();
int cellWidth = width / columnCount;
int cellHeight = height / rowCount;
int xOffset = (width - (columnCount * cellWidth)) / 2;
int yOffset = (height - (rowCount * cellHeight)) / 2;
if (cells.isEmpty()) {
for (int row = 0; row < rowCount; row++) {
for (int col = 0; col < columnCount; col++) {
Rectangle cell = new Rectangle(
xOffset + (col * cellWidth),
yOffset + (row * cellHeight),
cellWidth,
cellHeight);
cells.add(cell);
}
}
}
if (selectedCell != null) {
int index = selectedCell.x + (selectedCell.y * columnCount);
Rectangle cell = cells.get(index);
g2d.setColor(Color.BLUE);
g2d.fill(cell);
}
g2d.setColor(Color.GRAY);
for (Rectangle cell : cells) {
g2d.draw(cell);
}
g2d.dispose();
}
}
}
この例では、ウィンドウを使用してグリッドのサイズを変更しますが、セルを固定サイズにするのは簡単な変更です。
詳細については 2Dグラフィックス をチェックしてください
コンポーネントの例で更新
この例では、一連のJPanel
sを使用して各セルを表します。
各セルは固定の幅と高さで定義され、メインウィンドウでサイズ変更されません。
この例では、各セルパネルに独自のマウスリスナーがあります。メインパネルに単一のマウスリスナーがあり、代わりに作業負荷自体を管理するように、コードを再コーディングすることはそれほど難しくありません。
import Java.awt.BorderLayout;
import Java.awt.Color;
import Java.awt.Dimension;
import Java.awt.EventQueue;
import Java.awt.GridBagConstraints;
import Java.awt.GridBagLayout;
import Java.awt.event.MouseAdapter;
import Java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;
public class TestGrid02 {
public static void main(String[] args) {
new TestGrid02();
}
public TestGrid02() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 5; col++) {
gbc.gridx = col;
gbc.gridy = row;
CellPane cellPane = new CellPane();
Border border = null;
if (row < 4) {
if (col < 4) {
border = new MatteBorder(1, 1, 0, 0, Color.GRAY);
} else {
border = new MatteBorder(1, 1, 0, 1, Color.GRAY);
}
} else {
if (col < 4) {
border = new MatteBorder(1, 1, 1, 0, Color.GRAY);
} else {
border = new MatteBorder(1, 1, 1, 1, Color.GRAY);
}
}
cellPane.setBorder(border);
add(cellPane, gbc);
}
}
}
}
public class CellPane extends JPanel {
private Color defaultBackground;
public CellPane() {
addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
defaultBackground = getBackground();
setBackground(Color.BLUE);
}
@Override
public void mouseExited(MouseEvent e) {
setBackground(defaultBackground);
}
});
}
@Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
}
}
グリッド内に例よりも多くある場合に一部が複製されたため、境界線のレンダリングは好きではありませんでした。私はこの解決策がより良いと思います:
private int width;
private int height;
// ...
for (int row = 0; row <= this.height; row++) {
for (int col = 0; col <= this.width; col++) {
gbc.gridx = col;
gbc.gridy = row;
CellPane cellPane = new CellPane();
Border border = new MatteBorder(1, 1, (row == this.height ? 1 : 0), (col == this.width ? 1 : 0), Color.GRAY);
cellPane.setBorder(border);
this.add(cellPane, gbc);
}
}
編集:
元のコードが5x5セルである場合、10x10など、より多くのセルの内側のエッジが接触し、いくつかの場所に厚いグリッドを作成するため、私の解決策の方が優れています。スクリーンショットで見るのはいいことです 厚いグリッド
MouseMovedメソッドのMouseListenerの例では、セルの認識をスムーズにするために、xOffset/yOffsetを検討することをお勧めします。
int column = (x - xOffset) / cellWidth;
int row = (y - yOffset) / cellHeight;