In my project, I have got a class FramesUtil which contains a set of frames stored in a HashMap -
ConcurrentHashMap<Integer, Frame> frameMap
I have another class Arbiter.java that should render video using frames from frameMap.
However, I can only see the first frame when the playVideo() method is being called from Arbiter.java.
public static void main(String[] args) {
try {
FramesUtil.ensureExistence();
FrameReader reader = new FrameReader();
reader.readBinary();
playVideo();
} catch (Exception e) {
e.printStackTrace();
}
}
Looks like the JFrame is not getting updated with new BufferedImage in the loop during the iteration
Below is my playVideo method from Arbiter.java -
public static void playVideo() {
BufferedImage img;
JFrame frame = new JFrame();
GridBagLayout gLayout = new GridBagLayout();
frame.getContentPane().setLayout(gLayout);
JLabel lbIm1;
for(int i=0; (img=FramesUtil.frameMap.get(i).bufferedImage)!=null; i++) {
lbIm1 = new JLabel(new ImageIcon(img));
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.CENTER;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 1;
System.out.println(lbIm1);
frame.getContentPane().add(lbIm1, c);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
PS. I have tried creating new JFrame and GridBagLayout instances inside the for loop
Related
I am trying to create a grid of text fields which I envision would look like this:
I am trying to use Swing in order to do this but am having trouble creating the grid. I have tried both GridBagLayout and GridLayout in order to accomplish this but have had the same issue with both - I am unable to remove spaces between the text fields.
The above image is using grid bag layout. I have tried to change the insets as well as the weights of each text field but have not been able to get rid of the spaces between the fields.
The grid layout is slightly better:
But it has the same problem. I tried adding each text field to a JPanel and then created an empty border for each panel but this also did not work.
I have attached the code for both implementations. I am not committed to using a JTextField so if there is some other element that a user can type into I would be willing to try that out as well. Any help getting rid of the spaces between each text field would be greatly appreciated!
GridBagLayoutDemo
class GridBagLayoutDemo {
public static void addComponentsToPane(Container pane) {
GridBagLayout gbl = new GridBagLayout();
pane.setLayout(gbl);
GridBagConstraints c = new GridBagConstraints();
int rows = 2;
int cols = 2;
for(int i = 0; i < (rows + 1) * 3; i++){
JTextField textField = new JTextField(1);
textField.setFont( new Font("Serif", Font.PLAIN, 30) );
JPanel tempPanel = new JPanel();
tempPanel.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
tempPanel.add(textField);
c.gridx = i % (rows + 1);
c.gridy = i / (cols + 1);
c.gridheight = 1;
c.gridwidth = 1;
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.fill = GridBagConstraints.HORIZONTAL;
pane.add(tempPanel, c);
}
gbl.setConstraints(pane, c);
c.insets = new Insets(0,0,0,0);
}
public void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("GridBagLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set up the content pane.
addComponentsToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
GridBagLayoutDemo demo = new GridBagLayoutDemo();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
demo.createAndShowGUI();
}
});
}
}
GridLayoutDemo
class GridLayoutDemo {
public void createAndShowGUI() {
JFrame frame = new JFrame("GridLayout");
//frame.setOpacity(0L);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel parentPanel = new JPanel();
GridLayout layout = new GridLayout(3, 3, 0, 0);
layout.setHgap(0);
layout.setVgap(0);
parentPanel.setLayout(layout);
for(int i = 0 ; i < 9; i++){
JTextField textField = new JTextField();
textField.setHorizontalAlignment(JTextField.CENTER);
// JPanel tempPanel = new JPanel();
//textField.setBounds(0, 0, 10 , 10);
//textField.setFont( new Font("Serif", Font.PLAIN, 18));
//tempPanel.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
//tempPanel.add(textField);
// tempPanel.add(textField);
parentPanel.add(textField);
}
frame.add(parentPanel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
GridLayoutDemo demo = new GridLayoutDemo();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
demo.createAndShowGUI();
}
});
}
}
I think you will find that this is a issue with the MacOS look and feel, as it adds a empty border around the text fields to allow for the focus highlight
You can see it highlighted below
The simplest way to remove it, is to remove or replace the border, for example...
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
gbc.weighty = 1;
int rows = 3;
int cols = 3;
for (int index = 0; index < (rows * cols); index++) {
int row = index % rows;
int col = index / cols;
gbc.gridy = row;
gbc.gridx = col;
JTextField textField = new JTextField(4);
textField.setText(col + "x" + row);
textField.setBorder(new LineBorder(Color.DARK_GRAY));
add(textField, gbc);
}
}
}
}
I'm very new to java I have been doing basic stuff and for my final project we wanted to create a gui rpg. Our problem right now is we can't figure out how to open another program by clicking the gui button. My friends told me you guys use eclipse so I don't have to show imports. Keep in mind I'm in highschool so don't judge too harsh :D Here is our code:
public class Narnia {
private static final String BACKHGROUND_IMAGE_URL = "http://randomwallpapers.net/fantasy-castle-1920x1080-wallpaper328374.jpg";
protected void initUI() throws MalformedURLException {
JFrame frame = new JFrame(Narnia.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final ImageIcon backgroundImage = new ImageIcon(new URL(BACKHGROUND_IMAGE_URL));
JLabel mainPanel = new JLabel(backgroundImage) {
#Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
Dimension lmPrefSize = getLayout().preferredLayoutSize(this);
size.width = Math.max(size.width, lmPrefSize.width);
size.height = Math.max(size.height, lmPrefSize.height);
return size;
}
};
mainPanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.weightx = 1.0;
gbc.anchor = GridBagConstraints.WEST;
gbc.gridwidth = GridBagConstraints.REMAINDER;
for (int i = 0; i < 1; i++) {
mainPanel.add(new JButton("Play" + ("")), gbc);
}
for (int i = 0; i < 1; i++) {
mainPanel.add(new JButton("Credits " + ("")), gbc);
}
for (int i = 0; i < 1; i++) {
mainPanel.add(new JButton("Exit " + ("")), gbc);
}
// Let's put a filler bottom component that will push the rest to the top
gbc.weighty = 1.0;
mainPanel.add(Box.createGlue(), gbc);
frame.add(mainPanel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new Narnia().initUI();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
Here is the class we want to open:
public class chooseaclass {
private static final String BACKHGROUND_IMAGE_URL = "http://randomwallpapers.net/fantasy-castle-1920x1080-wallpaper328374.jpg";
protected void initUI() throws MalformedURLException {
JFrame frame = new JFrame(chooseaclass.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final ImageIcon backgroundImage = new ImageIcon(new URL(BACKHGROUND_IMAGE_URL));
JLabel mainPanel = new JLabel(backgroundImage) {
#Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
Dimension lmPrefSize = getLayout().preferredLayoutSize(this);
size.width = Math.max(size.width, lmPrefSize.width);
size.height = Math.max(size.height, lmPrefSize.height);
return size;
}
};
mainPanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(40, 40, 40, 40);
gbc.weightx = 1.0;
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridwidth = GridBagConstraints.REMAINDER;
for (int i = 0; i < 1; i++) {
mainPanel.add(new JButton("Archer" + ("")), gbc);
}
for (int i = 0; i < 1; i++) {
mainPanel.add(new JButton("Mage " + ("")), gbc);
}
for (int i = 0; i < 1; i++) {
mainPanel.add(new JButton("Knight " + ("")), gbc);
}
// Let's put a filler bottom component that will push the rest to the top
gbc.weighty = 1.0;
mainPanel.add(Box.createGlue(), gbc);
frame.add(mainPanel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new chooseaclass().initUI();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
You need to add a listener to whatever button you want. In this case, we'll use an ActionListener.
Let's just use this existing line that you already have: mainPanel.add(new JButton("Play" + ("")), gbc);
First of all, to make it simpler, let's put that JButton in a variable:
JButton playButton = new JButton("Play" + (""));
To add a listener, we need to use the method addActionListener().
Now add an ActionListener as an anonymous class so that we can implement a method that the system can call behind the scenes:
JButton playButton = new JButton("Play" + (""));
playButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
new chooseaclass.initUI() //insantiate a new chooseaclass instance
}
});
mainPanel.add(playButton, gbc);
Within the actionPerformed() method, I instantiated a chooseaclass. You can do whatever you want from there.
I wrote this code off the cuff without an editor so it may contain syntax errors.
I am trying to make a simple gui window with images.
Here's my code:
import java.awt.*;
import javax.swing.*;
public class Image extends JFrame
{
private ImageIcon [] image = new ImageIcon[10];
private JLabel [] label = new JLabel[10];
Image()
{
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
for(int i=0; i<10; i++)
{
for(int j = 0; j<10;j++)
{
image[i] = new ImageIcon(getClass().getResource((i+1) +".jpg"));
label[i] = new JLabel (image[i]);
c.fill = GridBagConstraints.REMAINDER;
c.gridx = j;
c.gridy = i;
add(label[i]);
}
}
}
public static void main(String[] args)
{
Image i = new Image();
i.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
i.setVisible(true);
i.pack();
i.setTitle("My Title");
}
}
What I am trying to do is after the counter exits the inner loop, it should go on a new line in the window.
But i get the whole thing in the same line. Any suggestions?
You need to pass the constraints as a parameter when adding the labels:
add(label[i], c);
instead of
add(label[i]);
Not directly related to the problem, but you should create the GUI in the event dispatch thread; also, call setVisible(true) on the frame only after it is otherwise ready.
Initially I have a deck Image and a text "Deck" just below the image which looks fine
public class GuiTut extends JPanel {
private GridBagConstraints c = new GridBagConstraints();
private JLabel deckLabel = new JLabel();
public GuiTut() {
setLayout(new GridBagLayout());
try {
deck = ImageIO.read(new File("resources/images/deck.jpg"));
} catch (Exception e) {}
c.gridx = 0;
c.gridy = 0;
JLabel deckPic = new JLabel(new ImageIcon(deck));
add(deckPic, c);
deckLabel.setText("Deck");
c.gridx = 0;
c.gridy = 1;
add(deckLabel, c);
}
But after I add my gridLayout panel, my whole GUI design has been messed up.
As you can see my deck image is not aligned properly with the first row of my gridLayout
and my text "deck" has been separated by a few wide space.
public class GuiTut extends JPanel {
private GridBagConstraints c = new GridBagConstraints();
private JLabel deckLabel = new JLabel();
private JPanel gridLayoutPanel = new JPanel(new GridLayout(2, 0));
private JLabel[] label = new JLabel[14];
public GuiTut() {
setLayout(new GridBagLayout());
try {
card = ImageIO.read(new File("resources/images/card.jpg"));
} catch (Exception e) {}
for(int i = 0; i < 14; i++) {
label[i] = new JLabel(new ImageIcon(card);
gridLayoutPanel.add(label[i]);
}
try {
deck = ImageIO.read(new File("resources/images/deck.jpg"));
} catch (Exception e) {}
c.gridx = 0;
c.gridy = 0;
JLabel deckPic = new JLabel(new ImageIcon(deck));
add(deckPic, c);
deckLabel.setText("Deck");
c.gridx = 0;
c.gridy = 1;
add(deckLabel, c);
c.gridx = 1;
c.gridy = 0;
add(gridLayoutPanel, c);
}
What I want is the deck image to be align with the first row of the gridLayout and the text "deck" just right below the deck image but I can't seem to get it.
HotLinked images
For the deck label, you can just the set the text of the label and set the vertical/horizontal text poistions
JLabel label = new JLabel(new ImageIcon(new URL(DECK_URL)));
label.setText("DECK");
label.setHorizontalTextPosition(JLabel.CENTER);
label.setVerticalTextPosition(JLabel.BOTTOM);
For the deck positioning problem, you can use a different layout manager like BorderLayout for outer panel, and a default flow layout for the deck panel. The cards will still be GridLayout. It's usually helpful to nest panels when you need to
Example
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class GuiTest {
private static final String DECK_URL = "http://i.stack.imgur.com/xNffR.png";
private static final String CARD_URL = "http://i.stack.imgur.com/uVS1D.png";
private static JPanel createDeckPanel() {
JPanel panel = new JPanel();
try {
JLabel label = new JLabel(new ImageIcon(new URL(DECK_URL)));
label.setText("DECK");
label.setHorizontalTextPosition(JLabel.CENTER);
label.setVerticalTextPosition(JLabel.BOTTOM);
panel.add(label);
} catch (Exception ex) {
ex.printStackTrace();
}
return panel;
}
private static JPanel createCenterPanel(int rows, int cols) {
JPanel panel = new JPanel(new GridLayout(rows, cols));
for (int i = 0; i < rows*cols; i++) {
try {
panel.add(new JLabel(new ImageIcon(new URL(CARD_URL))));
} catch (Exception ex) {
ex.printStackTrace();
}
}
return panel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
JPanel panel = new JPanel(new BorderLayout());
panel.add(createDeckPanel(), BorderLayout.LINE_START);
panel.add(createCenterPanel(2, 6));
JOptionPane.showMessageDialog(null, panel);
}
});
}
}
I'm trying to think of the best layout manager to achieve the picture below. I know absolute positioning is what I am used to, but I can't get the background image using this. GridBagLayout is excellent, but horrifically hard when ever I try I get a separate image for each grid.
Does anyone know an easy way out of this, or easy code to achieve the following?
There are several ways to do it. These are what I can think of at the moment:
Create a subclass of JComponent.
Override the paintComponent(Graphics g) method to paint the image that you want to display.
Set the content pane of the JFrame to be this subclass.
Some sample code:
class ImagePanel extends JComponent {
private Image image;
public ImagePanel(Image image) {
this.image = image;
}
#Override
protected void paintComponent(Graphics g) {
g.drawImage(image, 0, 0, null);
}
}
// elsewhere
BufferedImage myImage = ImageIO.read(...);
JFrame myJFrame = new JFrame("Image pane");
myJFrame.setContentPane(new ImagePanel(myImage));
Note that this code does not handle re-sizing the image to fit the JFrame, if that's what you wanted.
There are a number of ways you can achieve this.
The simplest might be to just use what's already available...
If you don't need the background to be scaled at run-time (ie you can get away with a non-resizable window), simply using a JLabel as the primary container could make your life significantly easier.
public class LabelBackground {
public static void main(String[] args) {
new LabelBackground();
}
public LabelBackground() {
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 LoginPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class LoginPane extends JLabel {
public LoginPane() {
try {
setIcon(new ImageIcon(ImageIO.read(getClass().getResource("/background.jpg"))));
} catch (IOException ex) {
ex.printStackTrace();
}
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.EAST;
gbc.insets = new Insets(2, 2, 2, 2);
gbc.gridx = 0;
gbc.gridy = 0;
JLabel nameLabel = new JLabel("Name: ");
nameLabel.setForeground(Color.WHITE);
JLabel passwordLabel = new JLabel("Password: ");
passwordLabel.setForeground(Color.WHITE);
add(nameLabel, gbc);
gbc.gridy++;
add(passwordLabel, gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx++;
gbc.gridy = 0;
add(new JTextField(20), gbc);
gbc.gridy++;
add(new JTextField(20), gbc);
gbc.gridy++;
gbc.insets = new Insets(10, 2, 2, 2);
gbc.anchor = GridBagConstraints.EAST;
add(new JButton("Submit"), gbc);
}
}
}
Updated with example of left alignment
At the end of the constructor, add...
JPanel filler = new JPanel();
filler.setOpaque(false);
gbc.gridx++;
gbc.weightx = 1;
add(filler, gbc);
You might like to take a look at How to use GridBagLayout for more details