我正在尝试编写一个自定义JPanel,它遵循包含JPanel的布局管理器(我正在使用gridbag)。我的自定义JPanel在这里粘贴的时间有点太长了,但是要覆盖所有要覆盖的方法的清单,以便使其工作。
以下是我自定义JPanel的摘录:
public class GridPanel extends JPanel implements MouseMotionListener, MouseListener{
private Rectangle offdutyRect, sbRect, driveRect, onRect;
private int delta = 60;
private int[][] gridArray;
int draggedStartX = -1;
int draggedStartY = -1;
private int dutyStatusSpacing = 60;
private int totalSpacing = 100;
public GridPanel(){
this.setSize(new Dimension(800, 100));
this.addMouseMotionListener((MouseMotionListener) this);
this.addMouseListener(this);
int gridArrayColumns = 24*60/delta;
gridArray = new int[4][gridArrayColumns];
int r = 0;
int rHeight = this.getHeight()/4;
offdutyRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, this.getWidth() - totalSpacing, rHeight);
r++;
sbRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, this.getWidth() - totalSpacing, rHeight);
r++;
driveRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, this.getWidth() - totalSpacing, rHeight);
r++;
onRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, this.getWidth() - totalSpacing, rHeight);
Rectangle rect = null;
for(r = 0; r < gridArray.length; r++){
if(r == 0){
rect = offdutyRect;
}else if(r == 1){
rect = sbRect;
}else if(r == 2){
rect = driveRect;
}else if(r == 3){
rect = onRect;
}
//I haven't actually derived any of these things, just my best guesses.
int len = gridArray[r].length;
int width = (int) (rect.getWidth()/len);
rect.setSize((int)(width*len), (int) rect.getHeight());
}
}
public void paintComponent(Graphics g){
g.clearRect(this.getX(), this.getY(), this.getWidth(), this.getHeight());
//the center black bar for duty status "placeholders"
g.setColor(Color.black);
g.drawRect(getX(), getY(), getWidth() - 1, getHeight() - 1);
g.drawRect((int)offdutyRect.getX(), (int)offdutyRect.getY() + (int)offdutyRect.getHeight()/2, (int)offdutyRect.getWidth(), 1);
g.drawRect((int)sbRect.getX(), (int)sbRect.getY() + (int)sbRect.getHeight()/2, (int)sbRect.getWidth(), 1);
g.drawRect((int)driveRect.getX(), (int)driveRect.getY() + (int)driveRect.getHeight()/2, (int)driveRect.getWidth(), 1);
g.drawRect((int)onRect.getX(), (int)onRect.getY() + (int)onRect.getHeight()/2, (int)onRect.getWidth(), 1);
g.setColor(Color.pink);
g.drawRect((int)offdutyRect.getX(), (int)offdutyRect.getY(), (int)offdutyRect.getWidth(), (int)offdutyRect.getHeight());
g.drawRect((int)sbRect.getX(), (int)sbRect.getY(), (int)sbRect.getWidth(), (int)sbRect.getHeight());
g.drawRect((int)driveRect.getX(), (int)driveRect.getY(), (int)driveRect.getWidth(), (int)driveRect.getHeight());
g.drawRect((int)onRect.getX(), (int)onRect.getY(), (int)onRect.getWidth(), (int)onRect.getHeight());
//draw the array
g.setColor(Color.green);
Rectangle rect = null;
for(int r = 0; r < gridArray.length; r++){
if(r == 0){
rect = offdutyRect;
}else if(r == 1){
rect = sbRect;
}else if(r == 2){
rect = driveRect;
}else if(r == 3){
rect = onRect;
}
//I haven't actually derived any of these things, just my best guesses.
int len = gridArray[r].length;
int width = (int) (rect.getWidth()/len);
int height = (int) rect.getHeight() - 2;
for(int c = 0; c < gridArray[r].length; c++){
if(gridArray[r][c] == 1){
int x = (int) (rect.getX() + width*c);
int y = (int) rect.getY() + 2;
g.fillRect(x, y, width, height);
}
}
}
}
//implement setSize
public void setSize(Dimension d){
if(gridArray == null){
int gridArrayColumns = 24*60/delta;
gridArray = new int[4][gridArrayColumns];
}
int r = 0;
int rHeight = this.getHeight()/4;
offdutyRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, (int)d.getWidth() - totalSpacing, rHeight);
r++;
sbRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, (int)d.getWidth() - totalSpacing, rHeight);
r++;
driveRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, (int)d.getWidth() - totalSpacing, rHeight);
r++;
onRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, (int)d.getWidth() - totalSpacing, rHeight);
Rectangle rect = null;
for(r = 0; r < gridArray.length; r++){
if(r == 0){
rect = offdutyRect;
}else if(r == 1){
rect = sbRect;
}else if(r == 2){
rect = driveRect;
}else if(r == 3){
rect = onRect;
}
//I haven't actually derived any of these things, just my best guesses.
int len = gridArray[r].length;
int width = (int) (rect.getWidth()/len);
rect.setSize((int)(width*len), (int) rect.getHeight());
}
}
}
以下是相对较短的自定义容器,我的自定义类的多个实例将被添加:
public class GridContainer extends JPanel implements ActionListener{
List<GridPanel> panels = new ArrayList<GridPanel>();
public GridContainer(){
GridBagLayout gb = new GridBagLayout();
this.setLayout(gb);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.weightx = .5;
c.weighty = .5;
c.fill = GridBagConstraints.HORIZONTAL;
BufferedImage img = null;
try {
img = ImageIO.read(this.getClass().getResource("/res/add.png"));
} catch (IOException e) { }
JButton addButton = new JButton();
addButton.setIcon(new ImageIcon(img));
addButton.addActionListener(this);
this.add(addButton, c);
}
public void actionPerformed(ActionEvent e) {
System.out.println("action performed" + panels.size());
this.setLayout(new GridBagLayout());
removeAll();
repaint();
panels.add(new GridPanel());
int r = 0;
GridBagConstraints c = new GridBagConstraints();
for(int i = 0; i < panels.size(); i++){
JLabel label = new JLabel("day " + i);
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = r;
c.weightx = 1;
c.weighty = 1;
this.add(label, c);
r++;
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = r;
c.weightx = 1;
c.weighty = 1;
c.fill = GridBagConstraints.HORIZONTAL;
this.add(panels.get(i), c);
r++;
}
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = r;
c.weightx = 1;
c.weighty = 1;
c.fill = GridBagConstraints.HORIZONTAL;
BufferedImage img = null;
try {
img = ImageIO.read(this.getClass().getResource("/res/add.png"));
} catch (IOException ex) { }
JButton addButton = new JButton();
addButton.setIcon(new ImageIcon(img));
addButton.addActionListener(this);
this.add(addButton, c);
repaint();
}
}
不要觉得有必要调试这段代码,只是调整我所处的位置。
答案 0 :(得分:5)
我正在尝试编写一个跟随包含JPanel
的layoutmanager的自定义JPanel
组件不关心它添加到哪个面板,因此它也不关心父面板使用的布局管理器。
自定义组件会覆盖getPreferredSize(),getMinimumSize()和getMaximumSize()方法,以便父容器的布局管理器可以使用这些建议来确定组件的实际大小。
然后在paintComponent()
方法中使用getWidth()和geHeight()方法来确定组件的实际大小。然后相应地绘制组件。您的逻辑需要确定如何根据最终大小绘制组件。
g.clearRect(this.getX(), this.getY(), this.getWidth(), this.getHeight());
您的绘画代码应该使用(0,0)作为X / Y位置,因为您试图清除面板的整个区域。 getX()/ getY()值可能不为零,因为父容器的布局管理器将确定面板的位置。
答案 1 :(得分:3)
super.paintComponent
。这非常重要,因为它为绘画准备了图形上下文,这在处理透明组件时非常重要
public class GridPanel extends JPanel implements MouseMotionListener, MouseListener {
private Rectangle offdutyRect, sbRect, driveRect, onRect;
private int delta = 60;
private int[][] gridArray;
int draggedStartX = -1;
int draggedStartY = -1;
private int dutyStatusSpacing = 60;
private int totalSpacing = 100;
public GridPanel() {
setBackground(Color.WHITE);
//this.setSize(new Dimension(800, 100));
this.addMouseMotionListener((MouseMotionListener) this);
this.addMouseListener(this);
int gridArrayColumns = 24 * 60 / delta;
gridArray = new int[4][gridArrayColumns];
int r = 0;
int rHeight = this.getHeight() / 4;
offdutyRect = new Rectangle(dutyStatusSpacing, r * rHeight, this.getWidth() - totalSpacing, rHeight);
r++;
sbRect = new Rectangle(dutyStatusSpacing, r * rHeight, this.getWidth() - totalSpacing, rHeight);
r++;
driveRect = new Rectangle(dutyStatusSpacing, r * rHeight, this.getWidth() - totalSpacing, rHeight);
r++;
onRect = new Rectangle(dutyStatusSpacing, r * rHeight, this.getWidth() - totalSpacing, rHeight);
Rectangle rect = null;
for (r = 0; r < gridArray.length; r++) {
if (r == 0) {
rect = offdutyRect;
} else if (r == 1) {
rect = sbRect;
} else if (r == 2) {
rect = driveRect;
} else if (r == 3) {
rect = onRect;
}
//I haven't actually derived any of these things, just my best guesses.
int len = gridArray[r].length;
int width = (int) (rect.getWidth() / len);
rect.setSize((int) (width * len), (int) rect.getHeight());
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
//the center black bar for duty status "placeholders"
g.setColor(Color.black);
g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g.drawRect((int) offdutyRect.getX(), (int) offdutyRect.getY() + (int) offdutyRect.getHeight() / 2, (int) offdutyRect.getWidth(), 1);
g.drawRect((int) sbRect.getX(), (int) sbRect.getY() + (int) sbRect.getHeight() / 2, (int) sbRect.getWidth(), 1);
g.drawRect((int) driveRect.getX(), (int) driveRect.getY() + (int) driveRect.getHeight() / 2, (int) driveRect.getWidth(), 1);
g.drawRect((int) onRect.getX(), (int) onRect.getY() + (int) onRect.getHeight() / 2, (int) onRect.getWidth(), 1);
g.setColor(Color.pink);
g.drawRect((int) offdutyRect.getX(), (int) offdutyRect.getY(), (int) offdutyRect.getWidth(), (int) offdutyRect.getHeight());
g.drawRect((int) sbRect.getX(), (int) sbRect.getY(), (int) sbRect.getWidth(), (int) sbRect.getHeight());
g.drawRect((int) driveRect.getX(), (int) driveRect.getY(), (int) driveRect.getWidth(), (int) driveRect.getHeight());
g.drawRect((int) onRect.getX(), (int) onRect.getY(), (int) onRect.getWidth(), (int) onRect.getHeight());
//draw the array
g.setColor(Color.green);
Rectangle rect = null;
for (int r = 0; r < gridArray.length; r++) {
if (r == 0) {
rect = offdutyRect;
} else if (r == 1) {
rect = sbRect;
} else if (r == 2) {
rect = driveRect;
} else if (r == 3) {
rect = onRect;
}
//I haven't actually derived any of these things, just my best guesses.
int len = gridArray[r].length;
int width = (int) (rect.getWidth() / len);
int height = (int) rect.getHeight() - 2;
for (int c = 0; c < gridArray[r].length; c++) {
if (gridArray[r][c] == 1) {
int x = (int) (rect.getX() + width * c);
int y = (int) rect.getY() + 2;
g.fillRect(x, y, width, height);
}
}
}
}
//implement setSize
// public void setSize(Dimension d) {
@Override
public void doLayout() {
if (gridArray == null) {
int gridArrayColumns = 24 * 60 / delta;
gridArray = new int[4][gridArrayColumns];
}
int r = 0;
int rHeight = this.getHeight() / 4;
offdutyRect = new Rectangle(dutyStatusSpacing, r * rHeight, (int) getWidth() - totalSpacing, rHeight);
r++;
sbRect = new Rectangle(dutyStatusSpacing, r * rHeight, (int) getWidth() - totalSpacing, rHeight);
r++;
driveRect = new Rectangle(dutyStatusSpacing, r * rHeight, (int) getWidth() - totalSpacing, rHeight);
r++;
onRect = new Rectangle(dutyStatusSpacing, r * rHeight, (int) getWidth() - totalSpacing, rHeight);
Rectangle rect = null;
for (r = 0; r < gridArray.length; r++) {
if (r == 0) {
rect = offdutyRect;
} else if (r == 1) {
rect = sbRect;
} else if (r == 2) {
rect = driveRect;
} else if (r == 3) {
rect = onRect;
}
//I haven't actually derived any of these things, just my best guesses.
int len = gridArray[r].length;
int width = (int) (rect.getWidth() / len);
rect.setSize((int) (width * len), (int) rect.getHeight());
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
我强烈建议您查看Performing Custom Painting