I use JInternalFrame to view a camera image, I get an image but it flashes/blinks very frequently, so I can barely see the image. I extend JFrame instead of JInternalFrame, everything works perfectly fine. Maybe JInternalFrame works differently to JFrame but I can't figure out the issue with the update.
public class CameraView extends JInternalFrame{
private JPanel contentPane;
VideoCap videoCapture = new VideoCap();
public CameraView(){
setSize(400, 400);
setLocation(100, 100);
contentPane = new JPanel();
setContentPane(contentPane);
contentPane.setLayout(null);
new MyThread().start();
}
#Override
public void paint(Graphics g){
g = contentPane.getGraphics();
g.drawImage(videoCapture.getOneFrame(), 0, 0, this);
}
class MyThread extends Thread{
#Override
public void run() {
for (;;){
repaint();
try { Thread.sleep(30);
} catch (InterruptedException e) { }
}
}
}
}
You have to remove
g = contentPane.getGraphics();
and
contentPane.setLayout(null);
Related
I want to draw an image on a JPanel which is displayed on a JFrame. I tested the paint method without the frame and it seemed to work, but as soon as I added the image on the frame it won't get shown. Instead I only see a very small square which displays a small area of the image.
Here's my code so far:
TestFrame class:
public class TestFrame extends JFrame {
private JFrame frame = new JFrame();
private JPanel jp = new JPanel();
public MyFrame() {
frame.setTitle("test");
frame.setSize(300, 300);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setLayout(new BorderLayout());
jp.setBackground(Color.YELLOW);
frame.add(jp, BorderLayout.CENTER);
jp.add(new DrawPanel());
jp.repaint();
frame.setVisible(true);
}
}
DrawPanel class:
public class DrawPanel extends JPanel {
private BufferedImage img;
public DrawPanel() {
try {
img = ImageIO.read(getClass().getResourceAsStream("/resources/heart.jpg"));
}
catch (IOException e) {
e.printStackTrace();
}
}
#Override protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, null);
}
}
Try with this in the method paintComponent():
g.drawimage(img.getImage(), 0, 0, null);
I've been trying to come up with a program that for a physics project, but I'm having problems. Here's the code:
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
public class Cannon extends JFrame {
Cannon() {
setTitle("Cannonball Experiment");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = getContentPane();
c.setLayout(new FlowLayout());
c.add(new ImagePanel());
c.add(new ModifierPanel());
setSize(400,600);
setVisible(true);
}
class ImagePanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(0,100,200,300);
}
}
class ModifierPanel extends Panel {
JLabel Text = new JLabel("Speed");
JTextField Tf = new JTextField(10);
ModifierPanel() {
add(Text);
add(Tf);
}
}
public static void main(String[] args) {
Cannon frame = new Cannon();
}
}
ModifierPanel displays fine but the JPanel, which I added before the Modifier, is not being displayed.
JPanel ImageJPanel doesn't show anything, so its dimension is (0,0).
Try to give your JPanel a dimension overriding method getPreferredSize like this:
class ImagePanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(0,100,200,300);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500,300); //for example
}
}
You're using FlowLayout that honors getPreferredSize so you won't have any problems. Try and let me know...
try buffered image in image panel ..
public class ImagePanel extends JPanel{
private BufferedImage image;
public ImagePanel() {
try {
image = ImageIO.read(new File("specify image name and path"));
} catch (IOException ex) {
// exception...
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
I was drawing my game on Canvas, all was god, but I changed it into a JPanel, but now its not working correctly, here are the codes, you can just copy them and you'll see where is the problem (I have a menu and after clicking on the button it should create new thread and there i want to draw, the problem in JPanel is that the button is able to see, its blinking and i can press it, in canvas it was fine, there wasn't any button). I solved it, that after clicking on the button I setted him unvisible (button.setVisible(false)), but these codes are just examples and in my game I have more buttons, so its not practical because I need them to see after the game ends. I think I just forgot an important method in JPanel, thx for help, codes:
//Main class representing menu
public class Sandbox extends JFrame{
Panel p = new Panel();
public static void main(String[] args) {
new Sandbox();
}
public Sandbox() {
setLayout(null);
setPreferredSize(new Dimension(200, 200));
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
final JButton but = new JButton("Button");
but.setBounds(0, 0, 50, 50);
but.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
p.start();
}
});
add(p);
add(but);
pack();
setVisible(true);
}
}
//Drawing on Canvas -> working well
public class Panel extends Canvas implements Runnable {
Thread t;
public Panel() {
setSize(new Dimension(200, 200));
setVisible(false);
}
public void start() {
t = new Thread(this);
t.start();
setVisible(true);
}
public void draw() {
BufferStrategy b = getBufferStrategy();
if(b == null) {
createBufferStrategy(3);
return;
}
Graphics g = b.getDrawGraphics();
g.setColor(Color.red);
g.fillRect(0, 0, 200, 200);
g.dispose();
b.show();
}
#Override
public void run() {
while(!t.isInterrupted()) {
try {
draw();
t.sleep(200);
} catch (InterruptedException ex) {}
}
}
}
//Drawing on JPanel -> here i can press the button after first click on it
public class Panel extends JPanel implements Runnable {
Thread t;
public Panel() {
setSize(new Dimension(200, 200));
setVisible(false);
}
public void start() {
t = new Thread(this);
t.start();
setVisible(true);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(0, 0, 200, 200);
}
#Override
public void run() {
while(!t.isInterrupted()) {
try {
repaint();
t.sleep(200);
} catch (InterruptedException ex) {}
}
}
}
Not sure I understand exactly what you are trying to do but you do have a couple of problems:
the setVisible(true) method should be invoked AFTER you have added all the components to the frame and packed the frame.
by default the content pane of a JFrame uses a BorderLayout. You code is adding two components to the CENTER of the BorderLayout, but a BorderLayout only allows you to add one component to the CENTER, so only the last component added will be displayed.
I'm trying to play around with JFrame/JPanels repaint(); and so forth, but when I start a thread, and call repaint via run while true, it only spits out a line of System.out.println("as"); which I put in place to check if loop was running.
So the question is:
Why is my drawings disappearing when calling repaint in a loop?
(It seems only a JFrame with the canvas_width/height is showing up, no panels etc.)
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(CANVAS_WIDTH, CANVAS_HEIGHT);
frame.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
frame.setVisible(true);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel(new GridLayout());
frame.getContentPane().add(p);
Something s = new Something();
p.add(s);
p.setBackground(Color.black);
frame.pack();
}
And the something class:
public class Something extends JPanel implements Runnable {
public Something(){
Thread t = new Thread();
t.start();
run();
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.cyan);
g.fillRect(0, 0, getWidth()-150, getHeight()-100);
g.setColor(Color.BLACK);
g.fillOval(10, 10, 25, 25);
}
#Override
public void run() {
while(true){
repaint();
System.out.println("as");
try {
Thread.sleep(1);
} catch (InterruptedException e){}
}
}
}
Any help regarding the contentpane is appreciated, since, I'm not sure this is done correctly.
Instead of calling Thread.sleep(n) in your Thread, implement a Swing Timer for repeating tasks. That ensures that repaint() is called on the Event Dispatch Thread.
See Concurrency in Swing for more details.
Also, repainting every 1 millisecond is being very optimistic.
Working SSCCE E.G. (Note this version actually changes the co-ords of the resulting paint operations, just so we know something is happening!
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Something extends JPanel {
static final int CANVAS_WIDTH = 400;
static final int CANVAS_HEIGHT = 100;
private int xDelta = 0;
public Something(){
ActionListener animater = new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
repaint();
}
};
Timer t = new Timer(10,animater);
t.start();
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.cyan);
g.fillRect(0, 0, getWidth()-(xDelta--), getHeight()-100);
g.setColor(Color.BLACK);
g.fillOval(xDelta, 10, 25, 25);
if (xDelta<0) {
xDelta = CANVAS_WIDTH;
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel(new GridLayout());
frame.getContentPane().add(p);
Something s = new Something();
p.add(s);
p.setBackground(Color.black);
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
}
}
Starting a Runnable in a new Thread is done with java.lang.Thread.Thread( Runnable ) constructor.
Calling a method of a GUI component outside the Swing event loop is not a good practice, use a Swing timer instead.
Your code becomes:
public static void main(String[] args) {
...
new Timer( 40, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
repaint
}
}).start();
...
}
I'm having this problem where an object that I've drawn isn't appearing in the GUI. I know it's being processed because data is being pushed to a log file. However, the graphic isn't appearing.
Here's some of my code:
public static void main(String[] args)
{
JFrame window = new JFrame();
window.setLayout(new BorderLayout());
window.setVisible(true);
}
There's a button and a few other widgets that I've placed here and there. The center pane (BorderLayout.CENTER) is where my DrawnObject is to be displayed.
// Called when button is pushed/clicked
public static void trigger()
{
DrawnObject shape = new DrawnObject();
window.setLayout(new BorderLayout());
window.getContentPane().add(shape, BorderLayout.CENTER);
window.pack;
}
public class DrawnObject extends JComponent()
{
#Override
public Dimension getMinimumSize()
{
return new Dimension(100, 100);
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(500, 500);
}
#Override
public Dimension getMaximumSize()
{
return new Dimension(700, 700);
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(10, 10, 10, 10);
}
}
I've tried casting the Graphics object as Graphics2D and using the appropriate draw methods, but that hasn't helped.
Try changing the color...
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(10, 10, 10, 10);
The graphics context color is set to the components background color by default
public class PaintTest01 {
public static void main(String[] args) {
new PaintTest01();
}
public PaintTest01() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new DrawPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DrawPane extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(30, 30);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(10, 10, 10, 10);
}
}
}
UPDATED
From your updated code in your question, it can't compile...
You create a JFrame named window in the constructor, which is a local variable...
public static void main(String[] args)
{
JFrame window = new JFrame();
window.setLayout(new BorderLayout());
window.setVisible(true);
}
Then you try and add the DrawObject to the window...
public static void trigger()
{
DrawnObject shape = new DrawnObject();
window.setLayout(new BorderLayout());
window.getContentPane().add(shape, BorderLayout.CENTER);
window.pack;
}
But because window is undefined, you example can't compile.
The only way that this would compile is if you had a static variable at the class level called window, which in that case, it should be producing a NullPointerException, unless you've initialised that variable
public class MyDrawing {
public static JFrame window = new JFrame();
This would mean you have two frames, one you created in the constructor and one your create as a static level class field. This won't work, because they are different instances
have to return PreferredSize from public class DrawnObject extends JComponent(), otherwise returns Dimension(0, 0);
Top-Level containers have got implemented BorderLayout, then window.add(shape, BorderLayout.CENTER); is proper code line and JComponent should be layed correctly
use pack() instead of invalidate(), this code line doesn't works, to invoke something for container layed by BorderLayout or GridLayout (e.i. ???), nor for container based on JComponent,JComponent havent implemented any LayoutManager in API, have to return PreferredSize
for better help sooner post an SSCCE
Try adding your DrawnObject to the windows content pane, and also don't forget to set a layout. Using a null layout is bad practice (your layout is set to null if you call on invalidate).
window.getContentPane().setLayout(new BorderLayout());
window.getContentPane().add(shape, BorderLayout.CENTER);
window.pack();
window.setVisible(true);
Also, try to skip the invalidate().