JPanel problem - repaint on resize on normal look - java

I have strange problem with JPanel. I am trying to show svg image ( SVG_class extends JSVGCanvas from batik jar). Problem is when I start this program I get this
and when I resize with pointer frame a little I get normal picture like this
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Ellipse2D;
import java.io.*;
import java.util.LinkedList;
import java.util.List;
import javax.swing.*;
import org.apache.batik.swing.JSVGCanvas;
public class Main {
static JScrollPane scrollpane;
// The frame.
protected JFrame frame;
public static void main(String[] args) {
final JFrame f = new JFrame("frame");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(700, 500);
f.setBackground(Color.blue);
SVG_class svg = new SVG_class();
JPanel p = new JPanel();
p.setSize(new Dimension(700, 500));
p.add(svg);
p.setBackground(Color.red);
scrollpane = new JScrollPane(p);
scrollpane.setPreferredSize(new Dimension(700, 500));
Container cont = f.getContentPane();
cont.add(scrollpane);
f.setVisible(true);
}
}
public class SVG_class extends JSVGCanvas {
private List<Type> list;
private int rad;
public boolean red_dot(int iX, int iY, String sX, String sY){
boolean b;
int x,y;
x=Math.abs(iX-(int)Double.parseDouble(sX));
y=Math.abs(iY-(getSize().height-(int)Double.parseDouble(sY)));
System.out.println("iX="+iX+" iY="+iY+" sX="+sX+" sY="+sY+" x="+x+" y="+y);
b=(x<=rad) &&(y<=rad);
return b;
}
public SVG_class(){
try {
this.list=CSV.getCSV("map2");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String fileName = "map2";
File file = new File("C:\\Users\\Gigabyte\\Desktop\\SVG\\"+fileName+".svg");
try {
this.setURI(file.toURL().toString());
this.addMouseListener(new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {
//
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseClicked(MouseEvent e) {
boolean found=false;
// System.out.println("pritisnuo si x="+e.getX()+" y="+e.getY());
int x,y;
for(int i=0; i<list.size() && !found;i++ ){
found=red_dot(e.getX(), e.getY(), list.get(i).getX(), list.get(i).getY());
}
if (found) {
System.out.println("pritisao!!!!");
}
System.out.println(" ");
}
});
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Can someone tell me what is mistake ? I tried with p.repaint but it didn't help.

Posting the source for SVG_class might make it easier to see what the problem is.
As it is, I suspect the problem is because you're not explicitly telling it what kind of layout to use.
If you want svg to take up the whole window you could do p.setLayout(new GridLayout(1, 1)); after you create p.

You should call the f.setSize(700, 500); just before showing.

SVG_class has probably set its size in the constructor. Don't do that and define the size at after calling the constructor.
EDIT: Try adding
f.pack();

Related

TicTacToe with Java Swing

At the moment I've got some problems with programming a TicTacToe game with Java Swing.
-the frame shall consist of 9 blank JLabels
-with a click X or an O appears
-the first click on a blank label shall show a X or O but more clicks on the same label have no more influence
-when the last click was an X, the next one should be an O
-it doesn't matter if you start with a X or an O
I wrote those two Classes:
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TicTacToe extends JFrame{
JPanel p = new JPanel();
SignLabel labels[]= new SignLabel[9];
public TicTacToe() {
super("TicTacToe");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(300,300);
p.setLayout(new GridLayout(3, 3));
for(int i=0;i<9;i++) {
labels[i] = new SignLabel();
p.add(labels[i]);
}
add(p);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
TicTacToe t = new TicTacToe();
}
});
}
}
SignLabel
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JLabel;
public class SignLabel extends JLabel implements MouseListener {
int value = 0;
public SignLabel() {
this.addMouseListener(this);
}
public void mouseClicked(MouseEvent e) {
value++;
value%=2;
switch(value) {
case 0:
if(this.getText() == null) {
this.setText("X");
} else if(this.getText() == "O") {
break;
} else if(this.getText() == "X") {
break;
}
case 1:
if(this.getText() == null) {
this.setText("O");
} else if(this.getText() == "O") {
break;
} else if(this.getText() == "X") {
break;
}
}
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
}
If i want to compile the code and start the java file, the wanted window will appear but either there are no labels or the mouse event doesn't work.
I guess the whole stuff with the getText() etc is wrong and the method above doesn't really do what I thought, too.
I would be glad about some help!
Thank you!
Here is your code corrected.
SignLabel.java
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JLabel;
public class SignLabel extends JLabel implements MouseListener {
static boolean value = false;
public SignLabel() {
this.addMouseListener(this);
}
public void mouseClicked(MouseEvent e) {
value = !value;
if(getText().length() == 0){
if(value){
setText("X");
}else{
setText("O");
}
}
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
}
TicTacToe.java
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.*;
import java.awt.*;
public class TicTacToe extends JFrame{
JPanel p = new JPanel();
SignLabel labels[]= new SignLabel[9];
public TicTacToe() {
super("TicTacToe");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(300,300);
p.setLayout(new GridLayout(3, 3));
for(int i=0;i<9;i++) {
labels[i] = new SignLabel();
labels[i].setBorder(BorderFactory.createLineBorder(Color.black));
p.add(labels[i]);
}
add(p);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
TicTacToe t = new TicTacToe();
}
});
}
}
Ok, a few things here:
your label are actually drawn, but without anything written to it you can't see them. At line 17 of ticTacToe.java you can see how I added borders to make sure the labels were there. They are.
Labels always have a String as a text. Empty, but they have. And empty String is a valid object, so the null comparision will be false. To see if the text is empty you can just check the length of the string getText() returns.
the whole check to see if there is X or O in the label is useless. Once you know there is something, you can just ignore the click.
I turned value to a boolean, so you can just switch between the two signs with a not. Also, to make it work, it must be static, otherwise every SignLabel you create will have its own value and you will always mark with an X (I forgot it and i've seen it myself, you remove the static and you can see it too.)

How to fix when JPanel.repaint() doesn't call paintComponent //nothing I found that work

I'm going to create a JPanel Howto, which is rendering 6 images in order and then add the back button to go back to title.
I'm trying check if it call paintComponent method in class howto or not. And it doesn't so the value i is still 0 and end up stuck in loop
Here's my Howto class
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import javax.swing.JPanel;
import Audio.HitSound;
import Graphic.DrawingUtility;
public class Howto extends JPanel implements Runnable{
private JButton back;
private static int i;
public Howto(){
this.setPreferredSize(new Dimension(800, 600));
this.setLayout(null);
repaint();
HitSound h = new HitSound();
i=0;
this.setVisible(true);
}
public void run() {
// TODO Auto-generated method stub
try {
while(i<6)
{
GameManager.frame.repaint();
Thread.sleep(10);
System.out.println("i: " + i);
}
} catch (Exception e) {
// TODO: handle exception
Thread.interrupted();
}
}
public void paintComponent(Graphics g){
if(GameManager.thread.isAlive()){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(DrawingUtility.getHowto(i), 0, 0, 800, 600,null);
i++;
}
}
}
and this what in my GameManager class
public static void startThread() {
thread = new Thread(howto);
thread.start();
}
public static void runHowto() {
howto = new Howto();
howto.setVisible(true);
frame.switchScene(howto);
howto.repaint();
startThread();
while (thread.isAlive()) {
//frame.repaint();
}
if (!thread.isAlive()) {
JButton back = new JButton();
back.setBorderPainted(false);
back.setContentAreaFilled(false);
back.setFocusPainted(false);
back.setOpaque(false);
back.setBounds(640, 446, 132, 132);
back.addMouseListener(new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
HitSound h = new HitSound();
h.play(3);
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
GameManager.goToTitle();
}
});
}
but when I call runHowto(); it's still looping and i == 0 and not increase i
So I think it's may have problem with paintComponent and repaint method
So please help me fixing it Thanks in advance :)
The while (thread.isAlive()) loop blocks the AWT Event Dispatch Thread (EDT).
You need to return to the event dispatch loop from runHowto. Have your Howto task to post back to the EDT with java.awt.EventQueue.invokeLater to construct your back button and presumably add it to a panel.

How to know the release listener is triggered after click operation or drag operation?

I asked a fuzzy question hours ago and hope this description can make it clear.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TestMouseEvent {
public void createUI(){
JFrame frame = new JFrame("Test Mouse Event");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
MainPanel mainPanel = new MainPanel();
mainPanel.setPreferredSize(new Dimension(800, 600));
mainPanel.addMouseListener(new ImageMouseListener());
mainPanel.addMouseMotionListener(new ImageMouseAdapter());
frame.add(mainPanel,BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
TestMouseEvent testMouseEvent = new TestMouseEvent();
testMouseEvent.createUI();
}
#SuppressWarnings("serial")
class MainPanel extends JPanel{
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setFont(new Font("Arial", Font.PLAIN, 20));
g.drawString("I'm a panel and I'm being listened now", 200, 300);
}
}
class ImageMouseListener implements MouseListener{
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println("clicked");
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println("pressed");
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println("released");
JOptionPane.showMessageDialog(null, "I only want to be showed when \"drag\" event over but not for click event!");
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
}
class ImageMouseAdapter extends MouseAdapter{
public void mouseDragged(MouseEvent e){
if (e.getModifiers() == InputEvent.BUTTON1_MASK) {
System.out.println("dragged");
}
}
}
}
I only want to show the JOptionPane right after the drag operation but not the click operation.So how can I know the difference?
Inside your ImageMouseAdapter set a flag (let's name if dragInProgressFlag) to true. On release check the flag. If it's true show the JOptionPane and reset it back to false.
First, unify your MouseListener and MouseMotionListener into a single class, you can do this simply by using MouseAdapter...
Second, add a instance variable to act as a flag to indicate if a drag operation is taking place...
class ImageMouseListener extends MouseAdapter {
private boolean isDragging = false;
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println("clicked");
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
if (isDragging) {
System.out.println("released");
JOptionPane.showMessageDialog(null, "I only want to be showed when \"drag\" event over but not for click event!");
}
isDragging = false
}
public void mouseDragged(MouseEvent e) {
if (e.getModifiers() == InputEvent.BUTTON1_MASK) {
isDragging = true;
System.out.println("dragged");
}
}
}
Create a single instance of the ImageMouseListener and add it as the mouseListener and mouseMotionListener for your panel...
ImageMouseListener handler = new ImageMouseListener();
mainPanel.addMouseListener(handler);
mainPanel.addMouseMotionListener(handler);
You could consider using the inbuilt Drag'n'Drop support within in Java, depending on what you want to achieve, for example, have a look at Java - How to drag and drop JPanel with its components

I am trying to add a JButton array that I added to a panel onto my JFrame, yet nothing is showing up

Here is my code:
For some reason nothing will appear on my screen, yet I don't know why, I believe I am initializing it correctly and adding it. Help?
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class main implements MouseListener{
final int WIDTH = 800, HEIGHT = 500, BOARD_WIDTH = 10, BOARD_HEIGHT = 10;
private JButton [][]buttons = new JButton[BOARD_WIDTH][BOARD_HEIGHT];
public static void main(String[] args) {
// TODO Auto-generated method stub
new main();
}
public main()
{
Start();
}
private void Start()
{
JFrame mainFrame = new JFrame("MineSweeper");
mainFrame.setVisible(true);
mainFrame.setSize(WIDTH,HEIGHT);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setLocationRelativeTo(null);
mainFrame.setResizable(false);
mainFrame.setLayout(new BorderLayout());
JPanel p1 = new JPanel();
p1.setLayout(new GridLayout(BOARD_WIDTH, BOARD_HEIGHT));
for(int x = 0; x < BOARD_WIDTH; x++)
for(int y = 0; y < BOARD_HEIGHT; y++)
{
buttons[x][y] = new JButton("01");
buttons[x][y].addMouseListener(this);
p1.add(buttons[x][y]);
}
mainFrame.add(p1, BorderLayout.CENTER);
}
#Override
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
Thanks for any help!
Also sorry for any confusion it is that my buttons wont appear on the screen not that the frame will no appear.
Call mainFrame.setVisible(true); last
private void Start()
{
JFrame mainFrame = new JFrame("MineSweeper");
// Move this...
//mainFrame.setVisible(true);
//...
mainFrame.add(p1, BorderLayout.CENTER);
// To here
mainFrame.setVisible(true);
}
You should also launch you application within the context of the EDT. Take a look at Initial Threads for more details
You should also avoid using a MouseListener on buttons, they have a ActionListener API which includes notification when the use clicks the button or "active" key (usually Enter or Space)

having problems with keyListener

i am trying to make a simple reaction test in java.
when the screen turns green i press space witch is supposed to change te boolean "clicked into false and stop the loop that measures time.
in reality the key listner does nothing.
am i adding the keay listener to the right compnent( jpanel panel)?
is there any other problems?
import java.awt.Color;
import java.awt.RenderingHints.Key;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
public class mainCheck {
// //////////////////////////////////////
public static void timeKeeper() {
boolean clicked=false;
long time = 10000;
try {
Thread.sleep(5000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
panel.setBackground(Color.GREEN);
while (time > 0 && !clicked) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
time--;
}
panel.setBackground(Color.gray);
long time2= 10000-time;
JLabel x = new JLabel("" +time2+"");
panel.add(x);
}
// //////////////////////////////////////
static boolean clicked;
JFrame frame;
static JPanel panel;
public mainCheck() {
frame = new JFrame();
panel = new JPanel();
clicked = false;
Handler handler = new Handler();
frame.addKeyListener(handler);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,500);
frame.setVisible(true);
}
// //////////////////////////////////////
public static void main(String[] args) {
mainCheck f = new mainCheck();
panel.getActionMap();
f.timeKeeper();
}
// //////////////////////////////////////
public class Handler implements KeyListener {
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
clicked = false;
System.out.println("space pressed");
}
}
}
}
do not use Thread.sleep(5000); block Event Dispatch Thread and during sleep you can lost all events to the already visible Swing GUI
use Swing Timer instead
Thread.sleep(1); could be proper delay for space enviroment, non_human, very short period attacking latency in Native OS (8-14miliseconds, depends of Native OS)
JLabel x = new JLabel("" +time2+""); and panel.add(x); in AWT/Swing isn't any notifiers that some, any, part of JComponents are removed or added, have to notify used LayoutManager (JPanel has FlowLayout in API) by using methods revalidate and repaint, e.g.
.
JLabel x = new JLabel("" +time2+"");
panel.add(x);
panel.revalidate();
panel.repaint();
Swing GUI should be created on Initial Thread
don't to use KeyListener use KeyBindings instead, otherwise you (are focus hunter) would need to set panel.seFocusable(true);
The problem is that you "e.getKeyCode()" always is "0" so
change for "e.getKeyChar()" and "(char)32"
the other problem is in that you put clicked = false and must be
"true"
And the last problem you have is in "timeKeeper()" you have to erase "boolean" because it is already declarated
Bad
public static void timeKeeper() {
boolean clicked=false
....}
Good
public static void timeKeeper() {
clicked=false
....}
This is the correct code:
import java.awt.Color;
import java.awt.event.*;
import javax.swing.*;
public class mainCheck {
// //////////////////////////////////////
public static void timeKeeper() {
clicked=false;
long time = 10000;
try {
Thread.sleep(5000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
panel.setBackground(Color.GREEN);
while (time > 0 && !clicked) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
time--;
}
panel.setBackground(Color.gray);
long time2= 10000-time;
JLabel x = new JLabel("" +time2+"");
panel.add(x);
}
// //////////////////////////////////////
static boolean clicked;
JFrame frame;
static JPanel panel;
Handler handler = new Handler();
public mainCheck() {
frame = new JFrame();
panel = new JPanel();
clicked = false;
frame.addKeyListener(handler);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,500);
frame.setVisible(true);
}
// //////////////////////////////////////
public static void main(String[] args) {
mainCheck f = new mainCheck();
panel.getActionMap();
f.timeKeeper();
}
// //////////////////////////////////////
public class Handler implements KeyListener {
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == (char)32) {
clicked = true;
System.out.println("space pressed");
}
}
}
}
It's a really bad idea to use Thread.sleep() to decrement the time value.
Use a Timer object instead:
public void myTimer(){
Timer myTimer = new Timer(delay, new ActionListener(){
public void actionPerformed(ActionEvent e){
//Stuff to do
}
});
}
Where delay is the amount of time you delay the timer. You start the timer with myTimer.start();

Categories