I have created an application which requires the reloading of an image several times throughout the program execution. Perhaps it's clumsy, but my implementation was to extend the Component class in a subclass and reload the image via a fileName argument to it's constructor. The code is included below:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.WindowConstants;
public class Grapher {
private static JFrame frame = new JFrame("Test Frame");
private static Graph graph = null;
private static JScrollPane jsp = null;
public Grapher(){
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
public void display(String fileName) {
if(jsp != null)
frame.getContentPane().remove(jsp);
graph = new Graph(fileName);
jsp = new JScrollPane(graph);
frame.getContentPane().add(jsp);
frame.setSize(graph.getPreferredSize());
frame.setVisible(true);
}
private class Graph extends Component{
BufferedImage img;
#Override
public void paint(Graphics g) {
g.drawImage(img, 0, 0, null);
}
public Graph(String fileName) {
setFocusable(false);
try {
img = ImageIO.read(new File(fileName));
} catch (IOException e) {System.err.println("Error reading " + fileName);e.printStackTrace();}
}
}
}
Anyway, my problem is that whenever I call the display command this window steals the focus of everything java, including eclipse, which can be really agravating. I even tried adding setFocusable(false) in the constructor, but it still manages to steal the focus. How do I tell it to be focusable but not focus automatically with construction?
Perhaps it's clumsy, but my implementation was to extend the Component class in a subclass and reload the image via a fileName argument to it's constructor
There is no need for a custom component. Just use a JLabel and the setIcon(...) method when you want to change the image.
Even if you did need a custom component you would not extend Component, you would extend JComponent or JPanel in a Swing application.
Setting a frame visible automatically gives the frame focus. You can try using:
frame.setWindowFocusableState( false );
Then you might need to add a WindowListener to the frame. When the window is opened you can reset the focusable state to true.
Related
In my program a JPanel component which is operated by listener using KeyBindings (changed that from KeyListeners already after reading about issues with focusing) is added to a JFrame. Task of this app is to simply move drawn figure around using arrow keys.
This works perfectly until i add another component before drawing board (JPanel with three buttons).
I tested both Keybindings and KeyListener and both methods have the same issue.
If I add components after drawing board keybindings starts to work again.
Here is my UI class where i add components.
EDIT: removed uncleaned code
I would like to understand Java a bit more so any answer is very appreciated.
Edit: I cleaned my code and created "minimal" example of the problem.
Thank you Andrew for heads up.
Program should print "movingup" in console after pressing arrow up.
The problem occurs here:
container.add(buttons); //after adding this Key Bindings stops working
container.add(board);
And the question is: Why order of adding components makes Key Bindings to stop working? If i add buttons after board Key Binding is working.
Class with the problem (used for creating frame and adding components)
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.WindowConstants;
public class UserInterface implements Runnable {
private static final String MOVE_UP = "moveUP";
private JFrame frame;
public UserInterface() {
}
#Override
public void run() {
frame = new JFrame("Board");
frame.setPreferredSize(new Dimension(500, 400));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout());
createComponents(frame.getContentPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void createComponents(Container container) {
DrawingBoard board = new DrawingBoard();
container.add(new JButton()); //after adding this figure stops moving - arrow keys doesn't work
container.add(board);
MovingUpwards up = new MovingUpwards(board);
board.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
board.getInputMap().put(KeyStroke.getKeyStroke("UP"), MOVE_UP);
board.getActionMap().put(MOVE_UP, up);
}
public JFrame getFrame() {
return frame;
}
}
Rest of the used classes for testing purposes:
import javax.swing.SwingUtilities;
public class Main {
public static void main (String[] args) {
UserInterface ui = new UserInterface();
SwingUtilities.invokeLater(ui);
}
}
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class DrawingBoard extends JPanel {
public DrawingBoard() {
super.setBackground(Color.WHITE);
}
#Override
protected void paintComponent (Graphics graphics) {
super.paintComponent(graphics);
}
}
import java.awt.Component;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
public class MovingUpwards extends AbstractAction {
private Component component;
public MovingUpwards(Component component) {
this.component = component;
}
#Override
public void actionPerformed(ActionEvent a) {
System.out.println("movingup");
}
}
The key bindings work fine for me. Check out the Motion Using Key Bindings example found in Motion Using the Keyboard.
I changed the code:
frame.add( content );
frame.add(left, BorderLayout.NORTH);
to:
frame.setLayout(new GridLayout());
frame.add(left);
frame.add( content );
to better simulate your logic.
If you need more help then read Andrew's comment above. Simplify your code to demonstrate the problem so we can "easily" test it by copying and compiling a single source file, the way you can test the code found in the link above.
I have two classes below: And I'm trying to make it so that calling FilledFrame would make certain shapes. I've tested it with a Line below, but it doesn't show up on the GUI. Is there something I'm doing wrong here? I also need to make a Card class that is able to modify some rectangle's positions, so would I need to make a graphics object in the main and enter it into FilledFrame and my Card class?
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import javax.swing.*;
public class FilledFrame extends JFrame implements ActionListener {
static int FRAME_WIDTH = 500;
static int FRAME_HEIGHT = 100;
Graphics g = getGraphics();
public FilledFrame () {
g.drawLine(1, 1, 100, 100);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setVisible(true);
}
private void createComponents() {
...
}
private void createCards() {
...
}
#Override
public void actionPerformed(ActionEvent e) {
}
public static void draw (Graphics g) {
g.fillRect(0, 50, 100, 150);
}
}
Main class:
import java.awt.Graphics;
import java.awt.Shape;
import java.awt.geom.Line2D;
import java.awt.geom.Line2D.Float;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.Canvas;
import javax.swing.JComponent;
import javax.swing.JPanel;
public class Main {
public static void main (String args[]) {
FilledFrame frame = new FilledFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.show();
}
}
Is there something I'm doing wrong here?
Sorry to say, but you're guessing at how to do Swing drawing, and while this might work with simple Java concepts, it won't for something as complex as Swing graphics.
Problems include:
Trying to draw directly within the JFrame -- never do this, but instead draw in a JPanel.
Calling getGraphics() on a component to get a Graphics resource. This will lead to your getting an unstable and short-lived Graphics object that can lead to either failed painting or NullPointerExceptions
Not drawing in an appropriate painting method.
You're using int literals in your drawing method parameters rather than int variables, making any drawing that you do do, fixed -- you can never move or change it.
Instead I suggest that you:
Create a class that extends JPanel and paint in that class.
Draw within this class's protected void paintComponent(Graphics g) method.
Don't forget to call the super's paintComponent method within your override so that your GUI cleans up any dirty pixels.
Then place that JPanel into the JFrame that needs to display it.
Use int fields (variables) not int literals (so-called "magic" numbers) for most of your drawing method parameters so that your drawings can change if you so desire while the program runs.
And most important, read and study the standard Swing graphics tutorials.
Resources:
The Really Big Index: the main tutorial where you should start.
Using Swing Components: how to create Swing GUI's
Lesson: Performing Custom Painting: introductory tutorial to Swing graphics
Painting in AWT and Swing: advanced tutorial on Swing graphics
I am learning how to add a VLCJ player to my application written with javaFX and FXML I read in other questions that i had to add to a canvas so i created a canvas in my FXML under an anchorpane.
<Canvas fx:id="mediaPlayerCanvas" height="174.0" layoutX="-4.0" layoutY="-2.0" width="595.0" />
then i initialised it in my application.java
#FXML
public void mediaPlayerCanvas()
{
mediaPlayer = new MediaPlayer();
}
and finally i created a MediaPlayer.java that includes this
package Lasercontroller;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
import javafx.embed.swing.JFXPanel;
import javafx.scene.canvas.Canvas;
import javafx.scene.layout.Pane;
import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.discovery.NativeDiscovery;
public class MediaPlayer {
private final Canvas canvas;
private final EmbeddedMediaPlayerComponent mediaPlayerComponent;
public synchronized void start(final String[] args) {
new NativeDiscovery().discover();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new MediaPlayer();
}
});
}
public MediaPlayer() {
canvas = new Canvas();
//canvasl.setBounds(100, 100, 600, 400);
String mediaLocation = "rtsp://192.168.1.175/stream1";
canvas.setVisible(true);
mediaPlayerComponent = new EmbeddedMediaPlayerComponent();
//panel.setContentPane(mediaPlayerComponent);
mediaPlayerComponent.getMediaPlayer().playMedia(mediaLocation);
}
}
When i run my application i get an exception The video surface component must be displayable
What have i done wrong? i have read lots of other question but i dont understand them.
The class uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent inherits from java.awt.Panel - it's an AWT component, completely unrelated with JavaFX. It's designed to be used with AWT or Swing.
At fist glance, one solution would seem to be to use a javafx.embed.swing.SwingNode to embed some Swing content inside your JavaFX application. However, this won't work, because EmbeddedMediaPlayerComponent is a heavyweight component, and the javadoc for SwingNode states : "The hierarchy of components contained in the JComponent instance should not contain any heavyweight components, otherwise SwingNode may fail to paint it" (see this answer).
So, as far as I know, tehre is no way to use EmbeddedMediaPlayerComponent in javaFX.
One possible solution is to use vlcj's DirectMediaPlayerComponent, and implement yourself the code to write each frame on a JavaFX Canvas. There is a relevant example on github. Note that this will not be as efficient (in terms of performances) as an EmbeddedMediaPlayerComponent.
Hi I want to make a window, a GUI, and put an image in it.
I watched a YT tutorial (https://www.youtube.com/watch?v=Ap20Qw77TzY) and copied everything similar but the Window I make has no image at all. I tried different file types like .jpg and different window sizes, matching the picture size but it doesn't help.
That's my code, I get no real errors, except a warning of:
The serializable class main does not declare a static final serialVersionUID field of type long,line 8
This method has a constructor,line 25
Code
package main;
import java.awt.Graphics;
import java.awt.Toolkit;
import javax.swing.*;
public class main extends JFrame {
/**
* author jan
*/
public main(String title){
super (title);
}
public void paint(Graphics gr) {
super.paint(gr);
gr.drawImage(Toolkit.getDefaultToolkit().getImage("Koppenhagen\\Pictures\\Herz.png"), 0, 0, this);
}
public static void main(String[] args) {
main window = new main("Mein Test!");
window.setSize(160,160);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
}
Use ImageIO.read over Toolkit.getImage, it will throw a IOException of the image can't be load for some reason
Check the location of the image. Your example is looking for a file in Koppenhagen\\Pictures, relative to the execution context of the program. You could use File#exists to check if the file actually exists where you think it is
Don't load resources within the any paint method, loading images can take time and painting should run as fast as possible
I'd discourage you from overriding paint of top level containers like JFrame. A JFrame contains a JRootPane, which contains, amongst other things, a contentPane all of which can be painted independently of its parent container. Instead, start with a JPanel and override its paintComponent method instead, then add this to an instance of JFrame
Here's a simple Swing application that draws an image.
You have to put the image in the same directory as the Java code.
package com.ggl.testing;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class DrawImage implements Runnable {
#Override
public void run() {
JFrame frame = new JFrame("Image");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scrollPane = new JScrollPane(new ImagePanel(getImage()));
frame.add(scrollPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private Image getImage() {
try {
return ImageIO.read(getClass().getResourceAsStream(
"StockMarket.png"));
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new DrawImage());
}
public class ImagePanel extends JPanel {
private static final long serialVersionUID = -2668799915861031723L;
private Image image;
public ImagePanel(Image image) {
this.image = image;
this.setPreferredSize(new Dimension(image.getWidth(null), image
.getHeight(null)));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
}
Learning to code, building a GUI to figure out how everything interacts. Trying to write a method to set focus on (component) at the points I need in the larger program - ie to call FocusGrabber(JTextField1) and have it set the input focus on JTextField1. In an attempt to do my best SSCCE, I've made a simple main that makes just enough GUI to give 2 textfields that should set focus on the second.
package ODIN;
import java.awt.Component;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
/*
*/
class FocusGrabber implements Runnable {
private JComponent component;
public FocusGrabber(JComponent component) {
this.component = component;
}
#Override
public void run() {
component.grabFocus();
}
public static void main(String[] args){
//draw and show the GUI
JFrame GUI = new JFrame();
GUI.setTitle("New Provider Interface");
GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTextField textID = new JTextField("providerID ", 20);
final JTextField textName = new JTextField("Provider Name ", 20);
GUI.add(textID);
GUI.add(textName);
GUI.pack();
GUI.setVisible(true);
FocusGrabber(textName);
}
}
Use requestFocusInWindow over grabFocus...
It would also be helpful if you called the run method at some point
Also, shouldn't it be more like
FocusGrabber fg = new FocusGrabber(textName);
fg.run();