Как исправить краску на существующий рисунок - PullRequest
0 голосов
/ 09 октября 2019

У меня проблемы с моим DrawPanel. Я хочу создать гриль, который должен быть нарисован с параметрами, заданными пользователем путем определения строк и двоеточий.

Например, я ввожу 3 строки и 5 двоеточий (:), Swing долженНарисуй это. Основная проблема заключается в том, что если я введу числа в TextField и нажму кнопку «Отрисовка», Swing отрисовывает новый гриль поверх старого. Кроме того, иногда программа не завершает некоторые строки или двоеточия, и я не понимаю, почему. Я уже добавил несколько чисел, таких как row-6, потому что за размах рисуй на несколько пикселей больше, чем нужно. Возможно, вы знаете решение этой проблемы тоже.

На картинке вы видите линии, которые слишком много. Я использую синюю линию, чтобы показать, как далеко должны пройти линии.

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                   
}

Ответы [ 2 ]

1 голос
/ 09 октября 2019

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);

Теперь вы сможете определить, правильна ли ваша логика.

0 голосов
/ 10 октября 2019

Таким образом, как предложено camickr , вам не следует добавлять какие-либо скрытые переменные в деление, или в строки / высоту, или в столбцы / ширину, потому что это кошмар обслуживания. Держитесь подальше от магических ценностей!

DrawPanel.paintComponent должен сделать несколько вещей.

  1. Не забудьте позвонить super()!
  2. Вам понадобитсячтобы определить толщину линии, чтобы вы знали, сколько нужно смещать.
  3. Сохраняйте свои единицы в виде значений с плавающей запятой, пока НЕ ​​НУЖНО установить их как целые числа.
  4. Утилизируйте впоследствии.

Более того, вы не хотите устанавливать переменные экземпляра в их объявлении, а через какой-то конструктор.

Кроме того, я добавил еще два поля для управления шириной и цветом линии, как показано ниже. Я также переработал макет так, чтобы он был действительно разборчивым с точки зрения обслуживания кода.

enter image description here

enter image description here

Бегунок

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();
    }
}
...