我正在创建一个绘制多边形并填充它的程序。然后显示按钮,以便用户可以向上,向下,向左或向右移动多边形。现在,当我调用repaint()方法时,我遇到了问题。
在paint()方法中,我创建了一个包含绘制和填充多边形的方法的类的新实例。这就是我的问题的原因。每次调用paint()时都会创建一个新的类实例,因此我所拥有的包含多边形点坐标的数组将重置为其初始值。
我的问题是攻击此问题的最佳方法是什么?如何在不创建新实例的情况下从paint()方法访问这些方法?我知道每个人都会说我可以使用像“NameOfClass.neededMethod();”这样的东西。这要求我把很多事情做成静态的,并且不会像希望的那样有效。
我感谢任何指针。
以下是我的类的代码,其中包含我需要访问的方法:
public class FillPolygon
{
int left_most_edge, right_most_edge, scan = 0;
double[] xcoord;
double[][] table = new double[4][200]; //2d array containing:
//[0][-] -> ymax, [1][-] -> ymin, [2][-] -> dx, [3][-] -> x
double[] px = {100, 150, 250, 300, 250, 150, 100}; //contains all x coord.
double[] py = {125, 100, 200, 150, 100, 200, 200}; //contains all y coord.
public void initializeTable()
{
int i, j;
for (i = 0; i < 4; i++)
{
for (j = 0; j < 200; j++)
{
table[i][j] = 0;
}//end for
}//end for
}//end initializeTable
public void upPressed()
{
for (int i = 0; i < py.length; i++)
{
py[i] -= 5;
}//end for
repaint();
}//end upPressed
public void downPressed()
{
for (int i = 0; i < py.length; i++)
{
py[i] += 5;
}//end for
repaint();
}//end upPressed
public void leftPressed()
{
for (int i = 0; i < px.length; i++)
{
px[i] -= 5;
}//end for
repaint();
}//end upPressed
public void rightPressed()
{
for (int i = 0; i < px.length; i++)
{
px[i] += 5;
}//end for
repaint();
}//end upPressed
public double max (double x, double y)
{ //determines the greater of two values
double max;
if (x > y)
max = x;
else
max = y;
return max;
}//end max
public void edgeInsert(double xStart, double yStart, double xEnd, double yEnd, int number_entered_edges)
{ //inserting edges into the edge table
int j = number_entered_edges; //removing the - 1 removes line on left side
double x;
if (yStart > yEnd)
{
table[0][j] = yStart;
table[1][j] = yEnd;
}//end if
else
{
table[0][j] = yEnd;
table[1][j] = yStart;
}//end else
if (table[1][j] == xStart)
x = xStart;
else
x = xEnd;
if (table[0][j] == yStart)
table[2][j] = -(-(xEnd - xStart) / (yEnd - yStart));
else
table[2][j] = -(xEnd - xStart) / (yEnd - yStart);
table[3][j] = x + table[2][j] / 2;
help(j);
}//end edgeInsert
public void loadTable(int number_vertices, int number_entered_edges,
double[] px, double[] py)
{ //take the x and y coordinates and build an edge table based off of them
int k;
double xStart, yStart, xEnd, yEnd;
xStart = px[number_vertices - 1];
yStart = trunc(py[number_vertices - 1]) + 0.5;
//start off with no edges in edge table
number_entered_edges = 0;
for (k = 0; k < number_vertices; k++)
{
xEnd = px[k];
yEnd = trunc(py[k]) + 0.5;
if (yStart == yEnd)
{
xStart = xEnd;
}//end if
else
{
//add edge to edge table
number_entered_edges++;
edgeInsert(xStart, yStart, xEnd, yEnd, number_entered_edges);
yStart = yEnd;
xStart = xEnd;
}//end else
}//end for
scan = (int)trunc(table[1][0]); //start at the top of the polygon
}//end loadTable
public void include(int number_entered_edges)
{ //pushing the right most edge
while ((right_most_edge + 1 < number_entered_edges) && (table[1][right_most_edge + 1] < scan))
{
right_most_edge++;
}//end while
}//end include
public void exclude()
{ //excluding edges that we no longer care about
for (int i = left_most_edge; i <= right_most_edge; i++)
{
if (table[0][i] < scan)
{
left_most_edge++;
for (int j = i; j >= left_most_edge; j--)
{
table[0][j] = table[0][j - 1];
table[2][j] = table[2][j - 1];
table[3][j] = table[3][j - 1];
}//end for
}//end if
}//end for
}//end exclude
public void help(int i)
{
double helpX, helpDX, helpYMax, helpYMin;
for (int j = i - 1; j >= 0; j--)
{
if ((table[1][j] == table[1][j + 1] && table[3][j] > table[3][j + 1]) || table[1][j] > table[1][j + 1])
{
helpYMax = table[0][j];
table[0][j] = table[0][j + 1];
table[0][j + 1] = helpYMax;
helpYMin = table[1][j];
table[1][j] = table[1][j + 1];
table[1][j + 1] = helpYMin;
helpDX = table[2][j];
table[2][j] = table[2][j + 1];
table[2][j + 1] = helpDX;
helpX = table[3][j];
table[3][j] = table[3][j + 1];
table[3][j + 1] = helpX;
}//end if
}//end for
}//end help
public void updateX()
{ //increment x based on dx
for (int i = left_most_edge; i <= right_most_edge; i++)
{
table[3][i] += table[2][i];
}//end for
}//end updateX
public void sortOnX()
{ //sorting x values from least to greatest in edge table
int l = 0;
double t;
xcoord = new double[right_most_edge - left_most_edge + 1];
for (int i = left_most_edge; i <= right_most_edge; i++)
{
xcoord[l] = table[3][i];
for(int j = l - 1; j >= 0; j--)
{
if (xcoord[j] > xcoord[j + 1])
{
t = xcoord[j];
xcoord[j] = xcoord[j + 1];
xcoord[j + 1] = t;
}//end if
}//end for
l++;
}//end for
}//end sortOnX
public void fillScan(Graphics g)
{ //determines the line to be drawn for filling
for (int i = 0; i < xcoord.length; i += 2)
{
drawMyHorizontalLine(g, (int)Math.round(xcoord[i]), scan, (int)Math.round(xcoord[i + 1]));
}//end for
}//end fillScan
public double trunc(double num)
{ //trucates the number passed in to remove any decimal
double rem;
if ((num % 2) == 0)
return num;
else
{
rem = num % 2;
return num - rem;
}//end else
}//end trunc
public void drawMyPolygon(Graphics g)
{ //draws the polygon
g.setColor(Color.RED);
g.drawLine((int)px[0], (int)py[0], (int)px[1], (int)py[1]);
g.drawLine((int)px[1], (int)py[1], (int)px[2], (int)py[2]);
g.drawLine((int)px[2], (int)py[2], (int)px[3], (int)py[3]);
g.drawLine((int)px[3], (int)py[3], (int)px[4], (int)py[4]);
g.drawLine((int)px[4], (int)py[4], (int)px[5], (int)py[5]);
g.drawLine((int)px[5], (int)py[5], (int)px[6], (int)py[6]);
g.drawLine((int)px[6], (int)py[6], (int)px[0], (int)py[0]);
}//end drawMyPolygon
public void drawMyHorizontalLine(Graphics g, int x1, int y, int x2)
{ //draws the line for filling
g.setColor(Color.GREEN);
g.drawLine(x1, y, x2, y);
}//end drawMyHorizontalLine
public void fillMyPolygon(Graphics g, int number_vertices, int number_entered_edges)
{ //calls methods to deal with edge table and fill the polygon
if (number_entered_edges < 3 || number_entered_edges > 200)
{
System.out.println("Polygon size error");
}//end if
else
{
loadTable(number_vertices, number_entered_edges, px, py);
while (left_most_edge < number_entered_edges)
{
scan++; //move down the screen
exclude();
updateX();
include(number_entered_edges);
sortOnX();
fillScan(g);
}//end while
}//end else
}//end fillMyPolygon
}//end FillPolygon
这是我的paint()方法,需要访问FillPolygon类中的方法才能实际绘制到JFrame:
@Override
public void paint(Graphics g)
{
FillPolygon f = new FillPolygon();
jButton1.setVisible(true);
jButton2.setVisible(true);
jButton3.setVisible(true);
jButton4.setVisible(true);
jButton5.setVisible(true);
jButton6.setVisible(true);
//initialize the edge table to all zeroes
f.initializeTable();
//begin filling the polygon
f.fillMyPolygon(g, 7, 7);
//draw polygon with red outline
f.drawMyPolygon(g);
}//end paint
答案 0 :(得分:6)
在paint()方法中,我创建了一个包含绘制和填充多边形的方法的类的新实例。这就是我的问题的原因。每次调用paint()时都会创建一个新的类实例,因此我所拥有的包含多边形点坐标的数组将重置为其初始值。
不要这样做。 paint方法(或者更好的是JPanel的paintComponent
方法覆盖)应仅用于绘画和绘画。你不应该在那里创建这样的实例,也不应该在那里改变类状态。只是画画,这就是它。请注意1)绘画可能由系统启动,并且不在您完全控制之下,2)每次调用repaint()
时都不能保证绘画,因此如果您的程序逻辑依赖于绘画方法,它有失败的风险。
我知道每个人都会说我可以使用&#34; NameOfClass.neededMethod();&#34;这要求我把很多事情做成静态的,并且不会像希望的那样有效。
没有人完全了解你的问题(而且我还不知道我害怕)以及了解OOP的人会建议这一点,相信我。
如需更具体的帮助,请显示更多代码,并详细说明问题。
修改
您不应该更改绘画中按钮的可见性。你不应该在paint中创建FillPolygon,而应该在类构造函数中执行一次。你也应该总是调用超级绘画方法,并且应该避免覆盖绘画,更喜欢paintComponent。例如:
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
@SuppressWarnings("serial")
public class DrawMovePolygonMain extends JPanel {
private DrawPolygonPanel drawPolygonPanel = new DrawPolygonPanel();
private MyMouseListener myMouseListener = new MyMouseListener();
public DrawMovePolygonMain() {
drawPolygonPanel.addMouseListener(myMouseListener);
JPanel buttonPanel = new JPanel();
buttonPanel.add(createDrawToggleButton());
for (PolyDirection dir : PolyDirection.values()) {
buttonPanel.add(new JButton(new DirectionAction(dir)));
}
setLayout(new BorderLayout());
add(drawPolygonPanel, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.PAGE_END);
}
private JComponent createDrawToggleButton() {
JToggleButton toggleButton = new JToggleButton("Draw Poly Points");
toggleButton.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
drawPolygonPanel.clearPoly();
drawPolygonPanel.resetPoints();
myMouseListener.setEnabled(true);
} else {
myMouseListener.setEnabled(false);
Path2D poly = new Path2D.Double();
List<Point> points = drawPolygonPanel.getPoints();
if (points == null || points.size() == 0) {
return;
}
poly.moveTo(points.get(0).getX(), points.get(0).getY());
for (Point point : points) {
poly.lineTo(point.getX(), point.getY());
}
poly.closePath();
drawPolygonPanel.clearPoints();
drawPolygonPanel.setPoly(poly);
}
}
});
return toggleButton;
}
private class DirectionAction extends AbstractAction {
private PolyDirection dir;
public DirectionAction(PolyDirection dir) {
super(dir.name());
this.dir = dir;
}
@Override
public void actionPerformed(ActionEvent e) {
drawPolygonPanel.move(dir);
}
}
private class MyMouseListener extends MouseAdapter {
private boolean enabled;
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public void mousePressed(MouseEvent e) {
if (enabled) {
drawPolygonPanel.addPoint(e.getPoint());
}
}
}
private static void createAndShowGui() {
DrawMovePolygonMain mainPanel = new DrawMovePolygonMain();
JFrame frame = new JFrame("DrawMovePolygonMain");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
@SuppressWarnings("serial")
class DrawPolygonPanel extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
private static final Color POLY_COLOR = Color.red;
private static final Color POLY_EDGE_COLOR = Color.blue;
private static final Stroke EDGE_STROKE = new BasicStroke(3f,
BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
private static final double SCALE = 10.0;
private static final int PT_RADIUS = 4;
private Path2D poly;
private List<Point> points = new ArrayList<>();
public void move(PolyDirection direction) {
double tx = direction.getTx() * SCALE;
double ty = direction.getTy() * SCALE;
AffineTransform transform = AffineTransform.getTranslateInstance(tx, ty);
poly.transform(transform);
repaint();
}
public void resetPoints() {
points = new ArrayList<>();
}
public void setPoly(Path2D poly) {
this.poly = poly;
repaint();
}
public void clearPoly() {
poly = null;
repaint();
}
public void addPoint(Point p) {
if (points != null) {
points.add(p);
}
repaint();
}
public List<Point> getPoints() {
return points;
}
public void clearPoints() {
points = null;
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (poly != null) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(POLY_COLOR);
if (poly != null) {
g2.fill(poly);
}
g2.setColor(POLY_EDGE_COLOR);
Stroke oldStroke = g2.getStroke();
g2.setStroke(EDGE_STROKE);
g2.draw(poly);
g2.setStroke(oldStroke);
}
if (points != null && points.size() > 0) {
g.setColor(Color.black);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (Point pt : points) {
int x = pt.x - PT_RADIUS;
int y = pt.y - PT_RADIUS;
int width = 2 * PT_RADIUS;
int height = width;
g.fillOval(x, y, width, height);
}
}
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
}
enum PolyDirection {
UP(0.0, -1.0), DOWN(0.0, 1.0), LEFT(-1.0, 0.0), RIGHT(1.0, 0.0);
private double tx;
private double ty;
private PolyDirection(double tx, double ty) {
this.tx = tx;
this.ty = ty;
}
public double getTx() {
return tx;
}
public double getTy() {
return ty;
}
}
请注意,我的绘图组件上方的示例代码扩展了JPanel,绘图方法是paintComponent方法,其内部的第一个方法调用是超级paintComponent方法。在其中,它所做的只是绘制多边形或用于创建多边形的点和别的。
答案 1 :(得分:0)
paint()
中的所有代码都应该移动到组件的构造函数中。
只有paint()
或更好的图纸才能在专为覆盖而设计的paintComponent()
中完成(而paint()
有一些内部功能,而BTW则因为没有调用而干扰了{ {1}})。