This is a JButton that needs to have action listener when clicked will call drawPiece method. Currently error is connect find symbol variable g.
JButton column3 = new JButton();
column3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
x = 2;
//.drawPiece(g);
column3.drawPiece(g);
}
});
This is the drawPiece method and where the graphics are initialized.
public void paintComponent(Graphics pen) {
super.paintComponent(pen);
drawBoard(pen);
drawPiece(pen);
boardarray();
}
public void drawPiece(Graphics g) {
x = x;
y=0;// fixed at 0
int turn=0;
boolean p1Win = false;
boolean p2Win = false;
//while(p1Win==false && p2Win==false) {
checkPiece();
g.setColor(Color.RED);
g.fillOval(10+x*110,10+y*110,100,100);
//checkWin();
p1Win = true;
}
Any suggestions are appreciated.
column3.drawPiece(g);
You should never invoke a painting method from a listener directly. If you want to repaint the component then you tell the component to repaint itself:
column3.repaint();
The makes a call to the RepaintManager to schedule the repainting. Ultimately the paintComponent() method will be invoked with the appropriate Graphics object.
Related
In my application, I made an array to control the flag images in my output. This worked fine but when I remove an element from my array the picture doesn't change at all.
class Flag{
Image FlagImage;
int FlagNum = 0;
public Flag(int FlagNum) {
this.FlagNum = FlagNum;
try{
FlagImage = ImageIO.read(new File("flag1.png"));
}catch(Exception e){
}
}
public void Update() {
}
public void Draw(Graphics g) {
//Draw Flag
g.drawImage(FlagImage, ((FlagNum) % 3+1) * 100-100, (int)((FlagNum) / 3) * 100+100, null);
}
}
public class Flags extends JPanel {
/**
* Creates new form Flags
*/
public Flags(){
initComponents();
FlagSet.add(new Flag(1));
final Timer timer =new Timer(10, new ActionListener(){
#Override
public void actionPerformed(final ActionEvent e){
repaint();
for (Flag f: FlagSet){
f.Update();
}
}
});
}
public static ArrayList<Flag> FlagSet = new ArrayList();
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
for (Flag f: FlagSet){
f.Draw(g);
}
}
I then try to add flags like so:
flagCounter = 4;
while(flagCounter > -1){
Flags.FlagSet.add(new Flag(flagCounter));
flagCounter--;
}
Which works fine but my image doesn't change if I put in a Flgas.FlageSet.remove(//Some flag)later on. Any ideas? Thanks in advance.
It looks like you're missing a call to repaint().
Repaint is a signal sent to the drawing component to tell it that something has changed, and that it needs to call the paint methods again. In this case, as your addition to your Flags list will change how it is drawn, you should simply call repaint() after you've finished adding your flags.
I am trying to to set up a KeyListener to respond to my keystrokes. I have already setup a mouselistener but for some reason I am un-able to get the keylistener to respond to any keystrokes.
I have created a class that implements KeyListener and overridden the functions. I then created an instance of the new class and added the handler to the JPanel and JFrame. Still no dice
public class main_program extends JFrame {
private int mX_cord, mY_cord,prior_selected_vertex, current_selected_vertex;
private int verticies_to_edge1, verticies_to_edge2;
private int radius =10;
private boolean vertex_selected1 = false, vertex_selected2 = false, edge_ready = false,delete_vertex_ready = false;
private Edge tempEdge = null;
private ArrayList<Integer> vertex_xcord = new ArrayList<Integer>();
private ArrayList<Integer> vertex_ycord = new ArrayList<Integer>();
private ArrayList<Edge> edge = new ArrayList<Edge>();
HandlerMouse handler = new HandlerMouse();
HandlerKey keyhand = new HandlerKey();
private JPanel masterPanel;
private JTextArea masterTextArea;
private JScrollPane masterScrollPane;
private Point point1, point2;
Graphics g;
public main_program(){
setTitle("Graph");
setSize(600, 400);
setDefaultCloseOperation(new JFrame().EXIT_ON_CLOSE);
//this must be set for custom layout of components
setLayout(null);
masterPanel = new JPanel();
masterPanel.setSize(600,300);
masterPanel.setLocation(0, 0);
masterPanel.setBackground(Color.WHITE);
masterPanel.addMouseListener(handler);
masterPanel.addMouseMotionListener(handler);
masterPanel.addKeyListener(keyhand);
masterTextArea = new JTextArea();
masterTextArea.setBackground(Color.green);
masterScrollPane = new JScrollPane();
masterScrollPane.add(masterTextArea);
masterScrollPane.setSize(600, 100);
masterScrollPane.setLocation(0, 300);
masterScrollPane.addMouseListener(handler);
masterScrollPane.addMouseListener(handler);
masterScrollPane.addKeyListener(keyhand);
add(masterPanel);
add(masterScrollPane);
setLocationRelativeTo(null);
setVisible(true);
}
public void paint(Graphics g){
super.paint(g);
for(int i = 0 ; i < vertex_xcord.size(); i++){
g.fillOval(vertex_xcord.get(i), vertex_ycord.get(i), radius, radius);
}
for(int i = 0 ; i<edge.size(); i++){
tempEdge = edge.get(i);
g.drawLine(vertex_xcord.get(tempEdge.vertex1), vertex_ycord.get(tempEdge.vertex1), vertex_xcord.get(tempEdge.vertex2), vertex_ycord.get(tempEdge.vertex2));
}
//g.fillOval(mX_cord, mY_cord, radius, radius);
//repaint();
}
private class HandlerKey implements KeyListener{
public void keyPressed(KeyEvent evt){
System.out.println("key pressed");
if(evt.getKeyCode() == KeyEvent.VK_ENTER && edge_ready){
edge.add(new Edge(prior_selected_vertex, current_selected_vertex));
edge_ready = false;
repaint();
}
}
public void keyReleased(KeyEvent evt){
System.out.println("key rel");
}
public void keyTyped(KeyEvent evt){
System.out.println("key type");
}
}
private class HandlerMouse implements MouseListener, MouseMotionListener{
public void mouseClicked(MouseEvent evt){
mX_cord = evt.getX()-5;
mY_cord = evt.getY()+15;
if( evt.getClickCount() == 1){
//mX_cord = evt.getX();
//mY_cord = evt.getY();
vertex_xcord.add(mX_cord);
vertex_ycord.add(mY_cord);
repaint();
}
else{
for(int i = 0 ; i < vertex_xcord.size(); i++){
if(Math.abs(vertex_xcord.get(i) - mX_cord ) < 15 && Math.abs(vertex_ycord.get(i) - mY_cord ) < 15 ){
if(vertex_selected1 == false){
prior_selected_vertex = i;
vertex_selected1 = true;
}
else{
current_selected_vertex = i;
vertex_selected2 = true;
}
System.out.println("YOU HAVE SELECTED A VERTEX: " + i);
break;
}
}
}
if(vertex_selected2 == true){
edge_ready = true;
verticies_to_edge1 = prior_selected_vertex;
verticies_to_edge2 = current_selected_vertex ;
vertex_selected1 = vertex_selected2 = false;
System.out.println("Ready for edge!");
}
else{
delete_vertex_ready = true;
}
}
public void mouseEntered(MouseEvent arg0)
{
}
public void mouseExited(MouseEvent arg0)
{
}
public void mousePressed(MouseEvent evt)
{
}
public void mouseReleased(MouseEvent arg0)
{
}
public void mouseDragged(MouseEvent e)
{
}
public void mouseMoved(MouseEvent e)
{
}
}
class Edge {
int vertex1, vertex2;
public Edge(int v1, int v2){
vertex1 = v1;
vertex2 = v2;
}
}
public static void main(String[] args){
main_program circle = new main_program();
}
}
You've got several problems with that program, and it suggests that you'd do well to read many of the Swing Q&A's on this site, because these problems (and your main problem) are quite common, and solutions are often posted.
As to your main problem, the problem again is very common: KeyListeners only work if the listened to component has focus. If it loses focus or is not focusable, then you're out of luck. The best solution is often not to use a KeyListener but rather the higher level and more flexible Key Bindings. Google will find the tutorials for you for this.
As for other problems with your code:
You're using null layout, a layout that leads to inflexible GUI's that are very difficult to upgrade and enhance, and that look terrible on all but your current platform and screen resolution. Solution: study and use the layout managers.
You're drawing directly into a JFrame's paint(Graphics g) method, which has risks as you risk messing up the painting of any and all of the JFrame's constituents by doing this. Much better to draw in a JPanel's paintComponent(Graphics g) method, and gain the benefit of Swing (rather than AWT) graphics including automatic double buffering.
Your class has a Graphics variable, g, which suggests that you're contemplating using a stored Graphics object either from a component or from the JVM. This increases the risk of your program throwing a NullPointerException when that Graphics object no longer exists, either that or drawing with it and but not seeing any effect. Solution: draw inside the painting method (again better with a JComponent's paintComponent method) only, or with the Graphics object from a BufferedImage.
You're adding a MouseListener directly to a JPanel but are drawing in a different component, the JFrame, and by doing so without taking insets into account, are placing points in the wrong location. Use the MouseListener on the same component that you're drawing on.
Again, please have a look around here, as I think you'll find a lot of treasures on this site that can be used to enhance your program.
Why can not I see the following output?
g2.drawString(new Date().toString(), 0, 150);
(i used g2 (global variable) for using g in paint method in inner class).
Thanks a lot in advance!
public class RedRect extends Frame
{
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new RedRect();
}
});
}
public static Point p;
RedRect()
{ super("RedRect");
try{
addWindowListener(new WindowAdapter()
{public void windowClosing(WindowEvent e){System.exit(0);}});
setSize (800, 600);
add("Center", new CvRedRect());
show();
}
catch(Exception ex){
}
}
}
class CvRedRect extends Canvas
{
Vector<Point> v=new Vector<Point>();
CvRedRect(){
addMouseListener((new MouseAdapter() {
public void mousePressed(MouseEvent evt){
if(v.size()<3){
v.add(evt.getPoint());
}
else{
flag=false;
//v.removeElementAt(0);
//v.add(evt.getPoint());
}
p=evt.getPoint();
repaint();
}
}));
}
Point p=new Point();
boolean flag=true;
int i=0;
public static Graphics g2;
public void paint(Graphics g)
{
try{
g2=g;
Dimension d = getSize();
int maxX = d.width - 1, maxY = d.height - 1;
g.setColor(Color.red);
g.drawRect(0, 0, maxX, maxY);
g.drawString("x ="+p.x, 10, 30);
g.drawString("y = " +p.y, 10, 60);
if(v.size()>2){
g2.drawLine(v.get(0).x,v.get(0).y,v.get(1).x,v.get(1).y);
g2.drawLine(v.get(0).x,v.get(0).y,v.get(2).x,v.get(2).y);
g2.drawLine(v.get(1).x,v.get(1).y,v.get(2).x,v.get(2).y);
Thread t=new Thread(){
public void run(){
try{
while(flag){
///The following comand//////
g2.drawString(new Date().toString(), 0, 150);
///////////////////////////
Thread.sleep(300);
System.out.println (v.size());
Thread.sleep(300);
}
}
catch(Exception ex){
System.out.println (ex.getMessage());
}
}
};
t.start();
}
//System.out.println ("size="+v.size());
if(!flag){
g.clearRect(0,0,maxX,maxY);
Thread.sleep(1000);
g.drawString("FINISH", 5, 30);
flag=true;
}
}
catch(Exception ex){
}
}
}
The reason your code isn't working is because you're using Graphics wrong. The Graphics object should not be a class field much less a static one. It is not a long-lived object, and so if you try to have it persist in this way, you'll end up with either a null reference or a non-null reference that doesn't work.
Instead if your program is an AWT program, then use the Graphics object inside of the paint method where the JVM supplies you with it when it calls paint. Otherwise if Swing do likewise with the paintComponent method.
Suggestions:
First and foremost, don't code AWT unless this is an absolute requirement for a class. Instead use Swing.
Next read the Swing graphics tutorials as they'll teach you all this and more.
Next do your drawing within the paintComponent(...) overload of a JPanel or other component that extends JComponent.
Don't forget to call the super.paintComponent(g) method within your override.
Don't forget to annotate your override with the #Override annotation.
Use a Swing Timer to do what you're currently using a while loop and Thread.sleep(...) to do.
I have a problem in this java code.
I want to make a painter program but whenever I choose a shape and draw it
all the shapes that were drawn before become the same as this shape. Here's the code.
I know that the problem is from the for statement in the paintComponent but what can I replace it with?
class inner extends JPanel implements MouseListener,MouseMotionListener{
private int oldx,oldy,newx,newy;
private Point point1,point2;
private Shape newRec,line1;
Rectangle currRec;
private Vector shape;
private boolean status,status1;
private int count=0;
private Object line;
inner(){
point1=point2=new Point(0,0);
shape = new Vector();
addMouseListener(this);
addMouseMotionListener(this);
}
public void mouseDragged(MouseEvent event) {
point2=event.getPoint();
newx = point2.x;
newy = point2.y;
if(Universal==7){
line = new Object(oldx,oldy,newx,newy);
status = true;
repaint();
}
currRec = new Rectangle(Math.min(point1.x,point2.x),Math.min(point1.y,point2.y),Math.abs(point1.x-point2.x),Math.abs(point1.y-point2.y));
status = true;
repaint();
}
#Override
public void mouseMoved(MouseEvent arg0) {}
public void mouseClicked(MouseEvent arg0) {}
public void mouseEntered(MouseEvent arg0) {}
#Override
public void mouseExited(MouseEvent arg0) {}
public void mousePressed(MouseEvent event) {
point1=event.getPoint();
oldx=event.getX();
oldy=event.getY();
}
#Override
public void mouseReleased(MouseEvent event) {
point2=event.getPoint();
newx=event.getX();
newy=event.getY();
//count++;
if(Universal==7){
line1 = new Shape(point1.x,point1.y,point2.x,point2.y);
shape.add(line1);
//Graphics g = getGraphics();
//g.setColor(colour);
//g.drawLine(point1.x,point1.y,point2.x,point2.y);
count++;
repaint();
}
else if(Universal==1||Universal==2||Universal==3||Universal==4||Universal==5||Universal==6){
newRec = new Shape(Math.min(point1.x,point2.x),Math.min(point1.y,point2.y),Math.abs(point1.x-point2.x),Math.abs(point1.y-point2.y));
shape.add(newRec);
count++;
repaint();
}
}
///// the problem is in here
public void paintComponent(Graphics g){
super.paintComponent(g);
Shape c;
g.setColor(colour);
for(int i=0;i<shape.size();i++){
c = (Shape) shape.get(i);
if(Universal==1){
g.drawRect(c.x, c.y, c.w, c.h);
if(status){
g.drawRect(currRec.x, currRec.y, currRec.width, currRec.height);
}
}
if(Universal==2){
g.fillRect(c.x, c.y, c.w, c.h);
if(status){
g.fillRect(currRec.x, currRec.y, currRec.width, currRec.height);
}
}
if(Universal==3){
g.drawRoundRect(c.x, c.y, c.w, c.h, c.w/4, c.h/4);
if(status){
g.drawRoundRect(currRec.x, currRec.y, currRec.width, currRec.height,currRec.width/4,currRec.height/4);
}
}
if(Universal==4){
g.fillRoundRect(c.x, c.y, c.w, c.h, c.w/4, c.h/4);
if(status){
g.fillRoundRect(currRec.x, currRec.y, currRec.width, currRec.height,currRec.width/4,currRec.height/4);
}
}
if(Universal==5){
g.drawOval(c.x, c.y, c.w, c.h);
if(status){
g.drawOval(currRec.x, currRec.y, currRec.width, currRec.height);
}
}
if(Universal==6){
g.fillOval(c.x, c.y, c.w, c.h);
if(status){
g.fillOval(currRec.x, currRec.y, currRec.width, currRec.height);
}
}
if(Universal==7){
g.drawLine(c.x, c.y, c.w, c.h);
if(status){
g.drawLine(line1.x, line1.y, line1.w,line1.h);
}
}
if(Universal==8){
shape.clear();
}
}
}
Universal is only ever going to be a given value at any given time.
Paints are not accumulative, they are destructive.
That is, each time paintComponent is called, all the previous contents is removed/wiped clean and you are expected to "repaint" the contents.
Instead of relying on a single flag, you should add the Shapes to some kind of List and redraw them all when ever paintComponent is called. Equally, you could simply add the "type" (int) to a List and process that list on each repaint
Take a look at Painting in AWT in Swing for an explanation of the paint process
See Custom Painting Approaches for two different ways to do this:
Add shapes to a List and then repaint all the Shapes from the list every time paintComponent() is invoked.
Draw Shapes to a BufferedImage and then just repaint the image ever time paintComponent() is invoked.
Neither example does exactly what you want, it only shows you the approach.
public void mousePressed(MouseEvent e) {
//Invoked when a mouse button has been pressed on a component.
if (e.getButton() == MouseEvent.BUTTON1) {
isDown = true;
System.out.println("isDown is now true");
}
if (e.getButton() == MouseEvent.BUTTON3) {
isDown2 = true;
System.out.println("isDown2 is now true");
}
do {
Point location = MouseInfo.getPointerInfo().getLocation();
int x = location.x - (drawingPanel.getLocationOnScreen()).x;
int y = location.y - (drawingPanel.getLocationOnScreen()).y;
drawingPanel.paint(drawingPanel.getGraphics(), (x - (x % 20) - 1), (y - (y % 20) - 1), 19, 19);
} while (isDown);
System.out.println("Mouse has been pressed down.");
}
public void mouseReleased(MouseEvent e) {
//Invoked when a mouse button has been released on a component.
if (e.getButton() == MouseEvent.BUTTON1) {
isDown = false;
System.out.println("isDown is now false");
}
if (e.getButton() == MouseEvent.BUTTON3) {
isDown2 = false;
System.out.println("isDown2 is now false");
}
System.out.println("Mouse has been released.");
}
This is what I have so far. My original intentions were to design the code so that the boolean isDown would be set to true when the mouse was pressed down and then I would have the while loop run while isDown is true. If the mouse button is released, I would set isDown to false in order to terminate the while loop.
What I am messing up here? Is it not possible for two MouseEvent methods to be running at the same time? The change in the isDown boolean variable is not being registered and I have an infinite while loop on my hands.
This is a classic violation of the Event Dispatching Thread.
All UI code is run from within a single thread. All events are dispatched the UI from this same thread, meaning that should you block this thread (using a loop or other blocking operation), no events will be dispatched. This will make your program look like it's hung.
Take a look at Concurrency in Swing for more details.
What you really should be doing is using a MouseMoitionListener to track drag events instead. Check out How to use Mouse Listeners for more details.
This drawingPanel.paint(drawingPanel.getGraphics(), (x - (x % 20) - 1), (y - (y % 20) - 1), 19, 19); also worries me to no end.
You should never be using getGraphics to perform custom painting. getGraphics can return null and is only a snap shot of the last paint cycle. Any painting done using this method will be removed/cleaned when another repaint occurs.
You should be creating a custom component (such as a JPanel) and overriding it's paintComponent method and performing any painting you need in it. Check out Performing Custom Painting for more details
Example
public class MouseDraggedTest {
public static void main(String[] args) {
new MouseDraggedTest();
}
public MouseDraggedTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Map<Point, List<Point>> mapPoints;
private Point currentPoint;
public TestPane() {
mapPoints = new HashMap<>(25);
MouseAdapter mouseListener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
currentPoint = e.getPoint();
mapPoints.put(currentPoint, new ArrayList<Point>(25));
}
#Override
public void mouseReleased(MouseEvent e) {
List<Point> points = mapPoints.get(currentPoint);
if (points.isEmpty()) {
mapPoints.remove(currentPoint);
}
currentPoint = null;
}
#Override
public void mouseDragged(MouseEvent me) {
List<Point> points = mapPoints.get(currentPoint);
points.add(me.getPoint());
repaint();
}
};
addMouseListener(mouseListener);
addMouseMotionListener(mouseListener);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Point startPoint : mapPoints.keySet()) {
List<Point> points = mapPoints.get(startPoint);
for (Point p : points) {
if (startPoint != null) {
g.drawLine(startPoint.x, startPoint.y, p.x, p.y);
}
startPoint = p;
}
}
}
}
}
Your are doing the while loop inside your mousePressed() method. It means you are blocking the Swing Event Dispatch Thread! As this method will not return as long as isDown is true, then the execution will not come back to the listener handler, which will never call your mouseReleased() listener.
As a general rule, you should never launch a long running operation in a listener, because it makes your GUI not respond to any event as long as it runs. Which in this case means forever! Any listener should not do more than set a few flags, and then return. It is necessary for your application to stay responsive.
One typical solution is to launch a new thread to do the long running work. It would free the Event Dispatching Thread and your mouseReleased() listener will be called.
The problem with this solution is that your work is painting on a Swing component. All graphics should be done in an overriden paintComponent method. As #MadProgrammer is already explaining you that, I won't go into details about it.