I'm making a video player with VLCJ; above and below I have two JPanels to display some information, and in the middle I have the canvas where the video is played. The problem is that when I resize the JFrame, the JPanels shrink and the Canvas expands, but when I place a button instead of the Canvas nothing changes. Do you know how to mantain the JPanels size when the JFrame is resized using GridBagLayout?
Snippet:
public class Test extends JFrame {
static Test frame;
static Canvas canvas;
static int video = 1;
JButton button;
public Test() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
JPanel followTo = new JPanel();
gbc.gridy=0;
gbc.weightx=1;
gbc.weighty= 0.11;
add(followTo, gbc);
canvas = new Canvas();
canvas.setBackground(Color.BLACK);
// button = new JButton();
gbc.gridy=1;
gbc.weightx=1;
gbc.weighty= 1.02;
gbc.fill= GridBagConstraints.BOTH;
add(canvas, gbc);
// add(button, gbc);
JPanel controls = new JPanel();
gbc.gridy=2;
gbc.weightx=1;
gbc.weighty=0.16;
add(controls, gbc);
}
public static void main(String[] args) {
frame = new Test();
frame.setSize(1200-54,864);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// /* Comment when using JButton
NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(),"C:\\Program Files\\VideoLAN\\VLC");
Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
MediaPlayerFactory mpf = new MediaPlayerFactory();
EmbeddedMediaPlayer emp = mpf.newEmbeddedMediaPlayer(new Win32FullScreenStrategy(frame));
emp.setVideoSurface(mpf.newVideoSurface(canvas));
emp.prepareMedia(url("Toulouse.mp4"));
emp.play();
// */
}
static String url (String video) {
String mrl = new Object().getClass().getResource("/media/guide.txt").getFile();
String url = mrl.replace("/", "\\").split("\\\\",2)[1].split("media")[0].concat("media\\"+video);
return url;
}
}
The problem is that when I resize the JFrame, the JPanels shrink and the Canvas expands,
Well you are telling us what is happening, but you haven't told us what you EXPECT should happen.
I would guess the problem is the way you are using the weighty constraints.
Based on the code provided I would suggest you should NOT use a GridBagLayout, but instead use a BorderLayout.
Then the code for adding the panels to the frame would simply be:
add(followTo, BorderLayout.PAGE_START);
add(canvas, BorderLayout.CENTER);
add(controls, Borderlayout.PAGE_END):
Now as the frame size changes, all the space will be given to the component in the CENTER. The components at the top/bottom would remain fixed in height.
Note you should also NOT be using static variables in your code.
Related
I'm aware there are several questions with the same title, and I've tried their answers but to no avail.
I'm getting the following result with my code:
It does not scroll as it should, and there's this empty little space to the right.
Here is the main code for the frame, mainpanel, list panel and the buttons panel that are inside the mainpanel.
public Tester2() {
JPanel mainPanel = new JPanel(); /////// MAIN PANEL
mainPanel.setLayout(new BorderLayout());
mainPanel.setPreferredSize(new Dimension(200, 400));
JPanel upperListPnl = new JPanel(); ////// LIST PANEL
upperPnlSetup(upperListPnl);
JPanel lowerBtnsPnl = new JPanel(); ///// BUTTONS PANEL
lowerBtnsPnl.setLayout(new BorderLayout());
JButton testButton = new JButton("Test the list");
testButton.addActionListener(e -> {
exampleModel.addElement("List has been tested");
updateExampleData();
});
lowerBtnsPnl.add(testButton);
mainPanel.add(upperListPnl, BorderLayout.CENTER);
mainPanel.add(lowerBtnsPnl, BorderLayout.SOUTH);
JFrame frame = new JFrame();
frame.add(mainPanel);
frame.setVisible(true);
frame.pack();
frame.setLocationRelativeTo(null);
}
Here is the code for the JList and the JScrollpane (upper panel):
public void upperPnlSetup(JPanel panel) {
panel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
exampleList = new JList<>(exampleModel);
JScrollPane jsp = new JScrollPane(exampleList, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
c.fill = GridBagConstraints.BOTH;
c.weighty = 1;
c.weightx = 0.75;
panel.add(exampleList, c);
c.weightx = 0.25;
panel.add(jsp, c);
}
And then the JList and model list as well as the data updating method:
private JList<String> exampleList;
private DefaultListModel<String> exampleModel = new DefaultListModel<>();
public void updateExampleData() {
exampleList.setModel(exampleModel);
}
I tried a FloatLayout, a BorderLayout, and a GridLayout (0,2 and 0,1) all of which didn't work. Finally, I settled for the GridBagLayout since it's seemingly always used for JLists and/or JScrollpanes, and I played with the GridBagConstraints as well as the positioning of the code but seem to always land on the same problem. I've tried giving the scroll pane a preferredSize, didn't do anything.
Okay so, apparently the problem was that I was adding the list to the panel. Adding it to the scrollpane, then adding the scrollpane to the panel was enough, so commenting out the
panel.add(exampleList, c);`
fixed the whole thing.
I am having issue where my JPanel is not setting up the size. I am not sure if is something to do with my JTab or JFrame. I am using GridBagLayout layout management. And for some reason are not able to set the size.
Here is a dummy code, following the same logic to my original source code:
FirstPanel.java
import javax.swing.*;
import java.awt.*;
public class FirstPanel extends JPanel {
private JLabel label1 = new JLabel("Label 1");
private JTextField textField1 = new JTextField();
private GridBagConstraints c = new GridBagConstraints();
public FirstPanel() {
//Size is not overriding
Dimension size = getPreferredSize();
size.width = 100;
setPreferredSize(size);
setBorder(BorderFactory.createTitleBorder("Border Title");
setLayout(new GridBagLayout());
addComponents();
}
private void addComponents() {
c.gridx = 0;
c.gridy = 0;
c.anchor = GridBagConstraints.NORTHWEST;
c.insets = new Insets(5, 0, 0, 0);
add(label1, c);
c.gridx = 1;
add(textField1, c);
c.weightx = 1;
c.weighty = 1;
add(new JLabel(""), c);
}
}
MainPanel.java
import javax.swing.*;
import java.awt.*;
public class MainPanel {
private JFrame frame = new JFrame("App");
private JPanel panel1 = new JPanel(new GridBagLayout());
private GridBagConstraints c = new GridBagConstraints();
private JTabbedPane tabPane = new JTabbedPane();
public MainPanel() {
addComponents();
frame.add(tabPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 350);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
}
private void addComponents() {
tabPane.addTab("Tab 1", new FirstPanel());
}
}
Main.java
public class Main {
public static void main(String[] args) {
new MainPanel();
}
}
Or at least have two JPanels,
Exactly.
Frist you create a main panel using a BorderLayout that you add to the tabbed pane.
Then you have a second panel for your labels and text fields (using whatever layout manager you want). Then you add this panel to the BorderLayout.LINE_START.
Then you add your scrollpane containing the JTable to the BorderLayout.CENTER of the main panel.
Read the tutorial on Layout Manager. Nest panels with different layout managers as required.
want to have JTable taking 50% of the other side.
Picking a random number like 50% is not the way to design a GUI. What happens if the frame is made smaller/larger. What happens to the space? Design the layout with flexibility in mind, just like your browser window is designed. There are always fixed areas where the size is determined by the components added and there is a flexible area that grows/shrinks as desired.
I am trying to create a frame, and when I am adding some components they don't listen to the sizes I give them, or locations - whenever I resize the frame, the components stick together, one aside another. Also, I have a scrollable text area, which takes the length and width of the text written in it. Plus, if I don't resize the frame the components don't show.
My code:
public static void main(String[] args){
new Main();
}
private void loadLabel(){
label.setBounds(0,0,269,20);
//Setting the icon, not relevant to the code.
panel.add(label);
}
private void loadInput(){
input.setBounds(0,20,300,60);
JScrollPane scroll = new JScrollPane (input);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scroll.setVisible(true);
scroll.setBounds(50,20,300,60);
panel.add(scroll);
}
private JPanel panel = new JPanel();
private JLabel label = new JLabel();
private JTextArea input = new JTextArea("Enter message ");
public Main() {
super("Frame");
setLocationRelativeTo(null);
setSize(300, 400);
setContentPane(panel);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
loadLabel();
loadInput();
}
Thanks in advance!
You shouldn't arrange your components using .setBounds(,,,) but instead arrange your
components using layout ( http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html ).
Plus you haven't set your label a text or icon so it's hard to see those component correctly. Here i'm using BoxLayout to manage your components vertically and put them on the EAST side of your frame by replacing setContentPane(panel); to getContentPane().add(panel,BorderLayout.EAST); to help us see your components correctly.
import java.awt.*;
import javax.swing.*;
public class Main extends JFrame {
public static void main(String[] args){
new Main();
}
private void loadLabel(){
label.setBounds(0,0,269,20);
//Setting the icon, not relevant to the code.
panel.add(label);
}
private void loadInput(){
input.setBounds(0,20,300,60);
JScrollPane scroll = new JScrollPane (input);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scroll.setVisible(true);
scroll.setBounds(50,20,300,60);
panel.add(scroll);
}
private JPanel panel = new JPanel();
private JLabel label = new JLabel("Your Label");
private JTextArea input = new JTextArea("Enter message ");
public Main() {
super("Frame");
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
setLocationRelativeTo(null);
setSize(300, 400);
getContentPane().add(panel,BorderLayout.EAST);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
loadLabel();
loadInput();
}
}
Write like this
loadLabel();
loadInput();
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Load the content then make it visible true
I have a JPanel(named mainJP) which has a few buttons and labels (uses BorderLayout). Next it adds another JPanel (named JP1) and inside it a ScrollPane with a JTable. I want to be able to resize JP2 and in turn all its child components (ScrollPane and JTable). So that I can see few more rows of the JTable without having to scroll. Also inorder to resize JP1, other siblings of JP1 should adjust themselves. Not sure how to achieve that.
As the image shows I already have a few features implemented - to entirely delete JP1, to expand/collapse JP1 view, to delete and add rows in the JTable.
So basically I want to be able to drag the mouse at bottom border of JP1 to vertically increase the size of JP1 and its child components (ScrollPane and JTable).
As described in a few of the below solutions, I am still confused at which level should I incorporate a JSpiltPane - as it allows only adding 2 components. I think all the JP1 should be in the JSplitPane. However there can be more than one JP1 components and they are dynamically added.
To add extra components to the JSplitPane is easy. Put a JPanel in each pane you want to show your components, then add the components to this panel -- you can customize the layout as needed.
Something like this will put a JSplitPane in an already create JFrame, add a JPanel to each Pane, and then add some JLabels to the left side, a JTextField to the right. The splitpane will expand to the size of the JFrame it's in.
JSplitPane splitPane = new JSplitPane();
JPanel leftPanel = new JPanel();
JPanel rightPanel = new JPanel();
JLabel label1 = new JLabel();
JLabel label2 = new JLabel();
JTextField textField = new JTextField();
GridBagConstraints gBC = new GridBagConstraints();
getContentPane().setLayout(new GridBagLayout());
leftPanel.setLayout(new GridBagLayout());
rightPanel.setLayout(new GridBagLayout());
// I'm not going to bother doing any layout of the label or textfield here
leftPanel.add(label1, new GridBagConstraints());
leftPanel.add(label2, new GridBagConstraints());
rightPanel.add(textField, new GridBagConstraints());
splitPane.setLeftComponent(leftPanel);
splitPane.setRightComponent(rightPanel);
gBC.fill = GridBagConstraints.BOTH;
gBC.weightx = 1.0;
gBC.weighty = 1.0;
getContentPane().add(splitPane, gBC);
pack();
These are two different problems. Resizing a JPanel on a mouse drag -- the easiest way for you is going to be to use two nested JSplitPanes. You would use one so you can drag horizontally, and another to drag vertically.
Alternatively, if you don't want split panes, you can try something like this method and create a custom JPanel. The borders are there to make the effect more visible. I personally don't like it as it's overly complicated.
public class ResizablePanel extends JPanel {
private boolean drag = false;
private Point dragLocation = new Point();
public ResizablePanel() {
setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
setPreferredSize(new Dimension(500, 500));
final JFrame f = new JFrame("Test");
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
drag = true;
dragLocation = e.getPoint();
}
#Override
public void mouseReleased(MouseEvent e) {
drag = false;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
if (drag) {
if (dragLocation.getX()> getWidth()-10 && dragLocation.getY() > getHeight()-10) {
System.err.println("in");
setSize((int)(getWidth()+(e.getPoint().getX()-dragLocation.getX())),
(int)(getHeight()+(e.getPoint().getY()-dragLocation.getY())));
dragLocation = e.getPoint();
}
}
}
});
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(this,BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
new ResizablePanel();
}
public void paintComponent(Graphics g) {
g.setColor(Color.red);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
As for the children resizing with it's parent, that one is pretty easy with GridBagLayout.
The important parts to remember in the GridBagConstraints are the fill, weightx and weighty.
You can just do something like this in your frame -- it will put a scrollpane with a JTable in it that will resize with the frame:
JScrollPane jScrollPane1 = new JScrollPane();
JTable jTable1 = new JTable();
GridBagConstraints gBC = new GridBagConstraints();
getContentPane().setLayout(new GridBagLayout());
jScrollPane1.setViewPortView(jTable1);
gBC.fill = GridBagConstraints.BOTH;
gBC.weightx = 1.0;
gBC.weighty = 1.0;
getContentPane().add(jScrollPane1, gBC);
I have a JPanel with a GridBagLayout inside of a JScrollPane. I also have an 'add' button within the JPanel which, when clicked, will be removed from the JPanel, adds a new instance of a separate component to the JPanel, then adds itself back to the JPanel. This sort of makes a growing list of components, followed by the 'add' button.
Adding new components works fine, the JPanel stretches to accommodate the new components, and the JScrollPane behaves as expected, allowing you to scroll through the entire length of the JPanel.
This is how the add works:
jPanel.remove(addButton);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = GridBagConstraints.RELATIVE;
jPanel.add(new MyComponent(), c);
jPanel.add(addButton, c);
jPanel.validate();
jPanel.repaint();`
Removal works by clicking a button inside the added components themselves. They remove themselves from the JPanel just fine. However, the JPanel keeps it's stretched-out size, re-centering the list of components.
This is how removal works:
Container parent = myComponent.getParent();
parent.remove(myComponent);
parent.validate();
parent.repaint();`
The question is, why does my GridBagLayout JPanel resize when adding components, but not when removing components?
You have to revalidate and repaint the JScrollPane, here is an example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SwingTest {
public static void main(String[] args) {
final JPanel panel = new JPanel(new GridBagLayout());
for (int i = 0; i < 25; i++) {
JTextField field = new JTextField("Field " + i, 20);
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridy = i;
panel.add(field, constraints);
}
final JScrollPane scrollPane = new JScrollPane(panel);
JButton removeButton = new JButton("Remove Field");
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (panel.getComponentCount() >= 1) {
panel.remove(panel.getComponentCount() - 1);
scrollPane.revalidate();
scrollPane.repaint();
}
}
});
JFrame frame = new JFrame("Swing Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(640, 480);
frame.setLocation(200, 200);
frame.getContentPane().add(scrollPane);
frame.getContentPane().add(removeButton, BorderLayout.SOUTH);
frame.setVisible(true);
}
}