我的DrawPanel出了点问题。我想做一个烤架-它应该用参数来绘制-由用户通过定义行和冒号给出。
例如,我输入3行5个冒号(:),Swing应该绘制它。主要问题是,如果我在TextField中输入数字并按下绘制按钮,Swing会在旧格栅上绘制新格栅。此外,有时程序无法完成某些行或冒号,我不明白为什么。我已经添加了一些数字,比如rows-6,因为swing绘制的像素比他应该绘制的多了几个像素。也许你也知道这个问题的解决方案。
在这张图上你可以看到太多的线条。我用一条蓝线来表示这些线应该走多远。

DrawPanel (JPanel)
import java.awt.Graphics;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* @author Serge Junk
*/
public class DrawPanel extends javax.swing.JPanel {
/**
* Creates new form DrawPanel
*
*/
private int rows = 1;
private int cols = 2;
public DrawPanel() {
initComponents();
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
// draw the rows
int rowHt = (height / rows)-1;
for (int i = 0; i <= rows; i++){
g.drawLine(0, i * rowHt, width, i * rowHt);
}
// draw the columns
int rowWid = (width / cols)-1;
for (int i = 0; i <= cols; i++){
g.drawLine(i * rowWid, 0, i * rowWid, height);
}
}
public void setRows(int pRows){
rows = pRows;
}
public void setCols(int pCols){
cols = pCols;
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
setPreferredSize(new java.awt.Dimension(300, 200));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
}// </editor-fold>
// Variables declaration - do not modify
// End of variables declaration
}MainFrame (JFrame)
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* @author Serge Junk
*/
public class MainFrame extends javax.swing.JFrame {
/**
* Creates new form MainFrame
*/
public MainFrame() {
initComponents();
}
public void updateView()
{
drawPanel1.repaint();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
drawPanel1 = new DrawPanel();
jLabel1 = new javax.swing.JLabel();
rowTextField = new javax.swing.JTextField();
jLabel2 = new javax.swing.JLabel();
colsTextField = new javax.swing.JTextField();
drawButton = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
javax.swing.GroupLayout drawPanel1Layout = new javax.swing.GroupLayout(drawPanel1);
drawPanel1.setLayout(drawPanel1Layout);
drawPanel1Layout.setHorizontalGroup(
drawPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 600, Short.MAX_VALUE)
);
drawPanel1Layout.setVerticalGroup(
drawPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 200, Short.MAX_VALUE)
);
jLabel1.setText("Lignes");
jLabel2.setText("Colonnes");
drawButton.setText("Draw");
drawButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
drawButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1)
.addGap(18, 18, 18)
.addComponent(rowTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 95, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel2)
.addGap(18, 18, 18)
.addComponent(colsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 95, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(25, 25, 25)
.addComponent(drawButton))
.addGroup(layout.createSequentialGroup()
.addGap(28, 28, 28)
.addComponent(drawPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 600, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(26, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(41, 41, 41)
.addComponent(drawPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 200, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 14, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(rowTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel2)
.addComponent(colsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(drawButton)))
.addContainerGap())
);
pack();
}// </editor-fold>
private void drawButtonActionPerformed(java.awt.event.ActionEvent evt) {
//E
int row = Integer.valueOf(rowTextField.getText());
int col = Integer.valueOf(colsTextField.getText());
//T
drawPanel1.setRows(row);
drawPanel1.setCols(col);
//S
updateView();
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JTextField colsTextField;
private javax.swing.JButton drawButton;
private DrawPanel drawPanel1;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JTextField rowTextField;
// End of variables declaration
}发布于 2019-10-10 04:04:39
Netbeans把新的烤架画在了旧的烤架上。
paintComponent()方法中的第一个语句应该是:
super.paintComponent(g);这将在您进行自定义绘制之前清除背景。
drawPanel1.setRows(row);
drawPanel1.setCols(col);
//S
updateView();不需要使用updateView()方法。相反,setRows(...)和setCols(...)方法都应该直接调用repaint()。也就是说,当组件的属性发生更改时,组件有责任重新绘制自身。
有时程序不能完成某些行或冒号,我不明白为什么。
int rowHt = height / rows-1;使用公式时要明确,这样我们才能确切地知道您想要什么,而不是依赖于编译器。所以你应该使用:
int rowHt = (height / rows) - 1;不要害怕为你的参数创建变量:
//g.drawLine(i * rowWid, 0, i * rowWid, height-5);
int xOffset = i * rowWidth;
int yEnd = height - 5;
g.drawLine(xOffset, 0, xOffset, yEnd);这样,您就可以轻松地添加调试代码,以准确地查看用于绘制直线的值:
System.out.println(xOffset + " : " + yEnd);现在,您应该能够确定您的逻辑是否正确。
发布于 2019-10-10 05:21:53
因此,正如camickr建议的那样,您不应该将任何隐藏变量添加到分区或行/高或cols /宽度,因为这是维护的噩梦。远离神奇的价值观!
DrawPanel.paintComponent必须做一些事情。
super()!此外,您不希望在它们的声明中设置实例变量,而是通过某种构造函数来设置。
另外,我添加了另外两个字段来控制线条宽度和颜色,如下所示。我还重新设计了布局,以便从代码维护的角度来看,它实际上是可读的。


跑步者
package question58310987;
import javax.swing.*;
public class Runner {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new MainFrame();
setLookAndFeel(frame);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
private static void setLookAndFeel(JFrame frame) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.updateComponentTreeUI(frame);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
}
}DrawPanel
package question58310987;
import java.awt.*;
import javax.swing.JPanel;
public class DrawPanel extends JPanel {
private static final long serialVersionUID = 1889951852010548809L;
private int rows;
private int cols;
private int thickness;
private Color fgColor;
private Color bgColor;
private boolean dirty;
private Stroke strokeRef;
public DrawPanel() {
this(3, 3);
}
public DrawPanel(int rows, int cols) {
this(rows, cols, 1, Color.BLACK, null);
}
public DrawPanel(int rows, int cols, int thickness, Color fgColor, Color bgColor) {
super();
this.rows = rows;
this.cols = cols;
this.thickness = thickness;
this.fgColor = fgColor;
this.bgColor = bgColor;
this.dirty = true; // initialized as true
}
private float getStrokeThickness(Graphics2D g2d) {
Stroke stroke = g2d.getStroke();
if (stroke instanceof BasicStroke) {
return ((BasicStroke) stroke).getLineWidth();
}
return 1.0f;
}
/**
* Re-evaluates the state of the properties.
*/
protected void commitProperties(Graphics2D g2d) {
if (dirty) {
strokeRef = new BasicStroke(this.thickness);
dirty = false;
}
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
commitProperties(g2d);
g2d.setStroke(strokeRef);
float lineSize = getStrokeThickness(g2d); // Calculate line thickness
float halfStroke = lineSize > 2.0f ? lineSize / 2.0f : 1.0f;
int width = this.getWidth();
int height = this.getHeight();
int maxWidth = (int) (width - halfStroke);
int maxHeight = (int) (height - halfStroke);
float yOffset = (((float) maxHeight - halfStroke) / (rows));
float xOffset = (((float) maxWidth - halfStroke) / (cols));
if (bgColor != null) {
g2d.setColor(bgColor);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
g2d.setColor(fgColor);
// Draw the horizontal lines
for (int row = 0; row < rows; row++) {
int y = (int) (row * yOffset + halfStroke);
g2d.drawLine((int) halfStroke, y, maxWidth, y);
}
g2d.drawLine((int) halfStroke, maxHeight, maxWidth, maxHeight); // Draw the final horizontal line
// Draw the vertical lines
for (int col = 0; col < cols; col++) {
int x = (int) (col * xOffset + halfStroke);
g2d.drawLine(x, (int) halfStroke, x, maxHeight);
}
g2d.drawLine(maxWidth, (int) halfStroke, maxWidth, maxHeight); // Draw the final vertical line
g2d.dispose(); // Clear changes
}
public String getFgColorHex() {
return String.format("#%02X%02X%02X", fgColor.getRed(), fgColor.getGreen(), fgColor.getBlue());
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
public int getCols() {
return cols;
}
public void setCols(int cols) {
this.cols = cols;
}
public int getThickness() {
return thickness;
}
public void setThickness(int thickness) {
this.thickness = thickness;
this.dirty = true;
}
public Color getFgColor() {
return fgColor;
}
public void setFgColor(Color fgColor) {
this.fgColor = fgColor;
}
public Color getBgColor() {
return bgColor;
}
public void setBgColor(Color bgColor) {
this.bgColor = bgColor;
}
}MainFrame
package question58310987;
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class MainFrame extends JFrame {
private static final long serialVersionUID = -2796976952328960949L;
private static final String DEFAULT_APP_TITLE = "Main Frame";
private DrawPanel drawPanel;
private JLabel rowLabel;
private JTextField rowTextField;
private JLabel colLabel;
private JTextField colTextField;
private JLabel thicknessLabel;
private JTextField thicknessTextField;
private JLabel colorLabel;
private JTextField colorTextField;
private JButton drawButton;
public MainFrame() {
this(DEFAULT_APP_TITLE);
}
public MainFrame(String title) {
super(title);
initialize();
addChildren();
}
protected void initialize() {
drawPanel = new DrawPanel();
drawPanel.setThickness(6);
drawPanel.setFgColor(Color.BLUE);
drawPanel.setPreferredSize(new Dimension(600, 200));
rowLabel = new JLabel("Rows");
rowTextField = new JTextField(Integer.toString(drawPanel.getRows()), 3);
colLabel = new JLabel("Columns");
colTextField = new JTextField(Integer.toString(drawPanel.getCols()), 3);
thicknessLabel = new JLabel("Thickness");
thicknessTextField = new JTextField(Integer.toString(drawPanel.getThickness()), 3);
colorLabel = new JLabel("Color");
colorTextField = new JTextField(drawPanel.getFgColorHex(), 6);
drawButton = new JButton("Draw");
drawButton.addActionListener(evt -> drawButtonActionPerformed(evt));
}
protected void addChildren() {
GridBagLayout verticalLayout = new GridBagLayout();
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(16, 16, 16, 16); // top, left, bottom, right
getContentPane().setLayout(verticalLayout);
getContentPane().add(drawPanel, gbc);
FlowLayout horizontalLayout = new FlowLayout();
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(horizontalLayout);
buttonPanel.add(rowLabel);
buttonPanel.add(rowTextField);
buttonPanel.add(Box.createHorizontalStrut(30));
buttonPanel.add(colLabel);
buttonPanel.add(colTextField);
buttonPanel.add(Box.createHorizontalStrut(30));
buttonPanel.add(thicknessLabel);
buttonPanel.add(thicknessTextField);
buttonPanel.add(Box.createHorizontalStrut(30));
buttonPanel.add(colorLabel);
buttonPanel.add(colorTextField);
buttonPanel.add(Box.createHorizontalStrut(30));
buttonPanel.add(drawButton);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.insets = new Insets(0, 16, 16, 16); // top, left, bottom, right
getContentPane().add(buttonPanel, gbc);
}
private void drawButtonActionPerformed(ActionEvent evt) {
int row = Integer.valueOf(rowTextField.getText().trim());
int col = Integer.valueOf(colTextField.getText().trim());
int thickness = Integer.valueOf(thicknessTextField.getText().trim());
String colorHex = colorTextField.getText().trim();
drawPanel.setRows(row);
drawPanel.setCols(col);
drawPanel.setThickness(thickness);
drawPanel.setFgColor(hexToColor(colorHex));
this.updateView();
}
public void updateView() {
drawPanel.repaint();
}
/**
* Supports both #FF0000 and #F00 formats.
*
* @param hex a hexadecimal color value from #000000 -> #FFFFFF
* @return
*/
public static final Color hexToColor(String hex) {
if (hex.startsWith("#")) {
hex = hex.replace("#", "");
}
if (hex.length() == 3) {
hex = splicePad(hex, 2);
}
int v = Integer.parseInt(hex, 16);
int r = (v & 0xFF0000) >> 16;
int g = (v & 0xFF00) >> 8;
int b = (v & 0xFF);
return new Color(r, g, b);
}
/**
* Splices each character after itself n-number of times.
*/
public static final String splicePad(String str, final int repeat) {
StringBuffer buff = new StringBuffer();
for (char ch : str.toCharArray()) {
for (int i = 0; i < repeat; i++) {
buff.append(ch);
}
}
return buff.toString();
}
}https://stackoverflow.com/questions/58310987
复制相似问题