Java fixed element's position - java

I need to build BlackJack game as an study project.
I want build it with SWING GUI. What I need it just divide the screen in 2 parts, and then to be able insert elements (in my case it's extended JButton with signed ImageIcon) using absolute (x, y) position relative to specified part.
Something like that:
I came from developing under Android, where you can work with elements in very simple way, and I feel lost in SWING. There aren't AbsoluteLayout or something like that?
Here is one example of my several attempts to this:
public void run() {
// TODO Auto-generated method stub
JFrame jFrame = new JFrame("Blackjack");
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = jFrame.getContentPane();
Insets insets = pane.getInsets();
URL url = ClassLoader.getSystemClassLoader().getResource("10_of_clubs.png");
BufferedImage bi = null;
try {
bi = ImageIO.read(url);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Image resizedImage = bi.getScaledInstance(128, 186, 0);
ImageIcon icon = new ImageIcon(resizedImage);
ImageButton imgButton = new ImageButton(icon);
imgButton.setPreferredSize(new Dimension(128, 186));
ImageButton imgButton2 = new ImageButton(icon);
imgButton.setPreferredSize(new Dimension(128, 186));
pane.setLayout(new GridBagLayout());
JPanel headPanel = new JPanel();
JPanel headPanel2 = new JPanel();
GridBagConstraints cns = new GridBagConstraints();
cns.gridx = 0;
cns.gridy = 0;
cns.weightx = 0.5;
cns.weighty = 0.2;
cns.anchor = GridBagConstraints.FIRST_LINE_START;
cns.fill = GridBagConstraints.BOTH;
headPanel.setBackground(Color.RED);
headPanel.add(imgButton, cns);
GridBagConstraints cns2 = new GridBagConstraints();
cns2.gridx = 0;
cns2.gridy = 0;
cns2.weightx = 0.5;
cns2.weighty = 0.2;
cns2.anchor = GridBagConstraints.FIRST_LINE_START;
cns2.fill = GridBagConstraints.CENTER;
headPanel2.setBackground(Color.BLUE);
headPanel2.add(imgButton2, cns2);
pane.add(headPanel);
pane.add(headPanel2);
jFrame.setSize(800, 600);
jFrame.setVisible(true);
jFrame.setLocationRelativeTo(null);
}
That what I get:
Tnx.

if you want absolute layout, please take a look at: http://docs.oracle.com/javase/tutorial/uiswing/layout/none.html
in general to read about layouts in java you can take a look at:
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
here is all java swing components: visual guide:
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
I think you can use JSplitPane (http://algo.math.ntua.gr/~symvonis/other-material/java_material/JavaTutorial/uiswing/components/splitpane.html) to create vertical separation

Since you have overlapping elements you can:
Use your existing JButtons with images inside a JLayeredPane. Put your cards on different layers for a clean rendering. Set the position of your Cards absolute with 'setBounds()'
Draw your cards with absolute position yourself using a Canvas. If you take this approach, you will also have to do your Click handling yourself (check if a click is inside a card.)

Related

Using JLabel to flip through images

I'm trying to flip through multiple images using previous and next button.
Currently, the layout is:
and this is my code:
public void createWalkthrough() {
if(currentframe != null) {
currentframe.setVisible(true);
return;
}
currentframe = new JFrame("Getting Started");
JPanel imagePanel = new JPanel();
imagePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
imageArea = new JLabel();
imagePanel.add(imageArea);
JButton previousButton = new JButton("Previous");
previousButton.addActionListener(this);
previousButton.setActionCommand("Previous");
JButton nextButton = new JButton("Next");
nextButton.addActionListener(this);
nextButton.setActionCommand("Next");
JPanel panelButtons = new JPanel();
panelButtons.setLayout(new BoxLayout(panelButtons, BoxLayout.LINE_AXIS));
panelButtons.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
panelButtons.add(Box.createRigidArea(new Dimension(10, 0)));
panelButtons.add(Box.createHorizontalGlue());
panelButtons.add(previousButton);
panelButtons.add(nextButton);
currentframe.setSize(439, 548);
currentframe.setResizable(false);
Container pane = currentframe.getContentPane();
pane.add(imagePanel, BorderLayout.CENTER);
currentframe.add(panelButtons, BorderLayout.PAGE_END);
currentframe.setVisible(true);
currentframe.requestFocusInWindow();
}
public void displayImage(int index) {
File[] imagesList = getImages();
File imageName = imagesList[index];
ImageIcon icon = new ImageIcon(imageName.getAbsolutePath());
Image image = icon.getImage().getScaledInstance(imageArea.getWidth(), imageArea.getHeight(), Image.SCALE_SMOOTH);
imageArea.setIcon(new ImageIcon(image));
}
public File[] getImages() {
File folder = new File("/Users/jwh/Desktop/img");
File[] listofImages = folder.listFiles();
return listofImages;
}
#Override
public void actionPerformed(ActionEvent e) {
if(base == null) {
return;
}
String selected = e.getActionCommand();
if(selected.equals("Previous")) {
pos = pos - 1;
if(pos < 0) {
pos = 0;
}
displayImage(pos);
} else if(selected.equals("Next")) {
pos = pos + 1;
if(pos >= getImages().length) {
pos = getImages().length;
}
displayImage(pos);
}
}
I'm not sure what I am doing wrong. I feel like I keep going around in circles by trying different things on different StackOverflow posts.
The error that I am currently getting is:
"Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException:
Width (0) and height (0) must be non-zero"
Any help would be greatly appreciated. Thank you!!
Your primary problem comes down to the compounding nature of your layouts and misunderstanding of the default layouts...
JPanel imagePanel = new JPanel();
imagePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
imageArea = new JLabel();
imagePanel.add(imageArea);
imagePanel, by default, is using a FlowLayout, which will attempt to honour the preferredSize of the components added to it.
JLabel, by default, has a preferredSize of 0x0.
So, when you do something like...
Image image = icon.getImage().getScaledInstance(imageArea.getWidth(), imageArea.getHeight(), Image.SCALE_SMOOTH);
you're actually passing 0x0 to the getScaledInstance method.
While there are number of ways to fix it, the simplest would be to use a layout manager which wants to fill the available space, like BorderLayout...
JPanel imagePanel = new JPanel(new BorderLayout());
imagePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
imageArea = new JLabel();
imagePanel.add(imageArea);
Feedback...
Okay, a number of small issues...
getScaledInstance does not produce the best result, nor is the fastest way to scale an image. Now, if you'd prefer not to use a library, like imgscalr, you could use something like Java: maintaining aspect ratio of JPanel background image and Quality of Image after resize very low -- Java to scale the images
It's some what of a personal thing, but I don't like the ImageIcon API, it doesn't provide feedback about why an image might not have been loaded and doesn't support a large range of image formats.
Personally, I prefer to use the ImageIO API instead. See Reading/Loading an Image

Swing components not moving to desired cell in GridBagLayout

I'm trying to create a simple UI for a program that can read a file, write to a file and search for text within a file. I have most of my Components created, the problem is that they're all being "drawn" in the same (center) cell. I've tried applying weights, widths, etc. all to no avail.
Here's my base code for the UI:
public void GUI(){
//Create main window for Program
JFrame mainWindow = new JFrame("Simple Data Base"); //Init frame
mainWindow.setSize(500, 400); //Set frame size
mainWindow.setVisible(true); //Make frame visible
//Create panel for the main window of the GUI
JPanel simpleGUI = new JPanel( new GridBagLayout());
GridBagConstraints gbCons = new GridBagConstraints();
simpleGUI.setBackground(Color.cyan);
//Create button linking to read function
JButton readButton = new JButton("Read"); //Init button, and give text
gbCons.fill = GridBagConstraints.BOTH;
gbCons.gridx = 0;
gbCons.gridy = 1;
//Create button linking to the search function
JButton searchButton = new JButton("Search");
gbCons.fill = GridBagConstraints.BOTH;
gbCons.gridx = 1;
gbCons.gridy = 1;
//Create label prompting user to specify desired function
JLabel promptText = new JLabel("Click 'Read' to read a file, 'Search' to search within a file, 'Write' to write to a file:");
gbCons.fill = GridBagConstraints.BOTH;
gbCons.gridx = 0;
gbCons.gridy = 0;
//Add components to Main window
mainWindow.getContentPane().add(simpleGUI);
simpleGUI.add(promptText, gbCons);
simpleGUI.add(readButton, gbCons);
simpleGUI.add(searchButton, gbCons);
}
the problem is that they're all being "drawn" in the same (center) cell.
simpleGUI.add(promptText, gbCons);
simpleGUI.add(readButton, gbCons);
simpleGUI.add(searchButton, gbCons);
You are using the same GridBagConstraints for each component so the contraints are identical for each component.
You neeed to:
set the constraints
add the component to the panel using the constraints
repeat steps 1 and 2.
For example:
JButton readButton = new JButton("Read");
gbCons.fill = GridBagConstraints.BOTH;
gbCons.gridx = 0;
gbCons.gridy = 1;
simpleGUI.add(readButton, gbCons);
JButton searchButton = new JButton("Search");
gbCons.fill = GridBagConstraints.BOTH;
gbCons.gridx = 1;
gbCons.gridy = 1;
simpleGUI.add(searchButton, gbCons);
I suggest you read the section from the Swing tutorial on How to Use GridBagLayout for more information and examples.
Download the demo code and use that example as your starting code. The demo code will show you how to better structure your class by:
NOT extending JFrame
Creating the GUI on the Event Dispatch Thread
Use the pack() method, NOT the setSize(...) method
Make the frame visible AFTER all components have been added to the frame

Adapting pixels of the image depending files and rows

I have this function where I receive String[][], f (rows), and c (columns). I've got to adapt my labels occupying all of my frame (1270,750).
For example, if I receive:
f=3 and c=3, the images will have: (423.333,250.) pixels
f=10 and c=10, the images will have (127,75) pixels.
I've proved with all the functions which are in the example, but it doesn't work. Any idea how to do it?
public void inicialitzamatriu(String[][] arraystrings,int f,int c) {
ff=f;
cc=c;
compsToExperiment=new JPanel();
GridLayout experimentLayout = new GridLayout(ff,cc);
compsToExperiment.setLayout(experimentLayout);
this.setContentPane(compsToExperiment);
for (int filas=0;filas<ff;filas++){
for (int columnas=0;columnas<cc;columnas++){
if (arraystrings[filas][columnas].equals("gat")){
JLabel cat2 = new JLabel();
cat2.resize(1270/cc, 750/cc);
cat2.setIcon(new ImageIcon("cat.png"));
compsToExperiment.add(cat2);
/*cat2.getSize();
//cat2.getWidth();
//cat2.getHeight();
cat2.resize(width, height);
cat2.setBounds(x, y, width, height)
cat2.setSize(width, height)
cat2.
*/
}
if (arraystrings[filas][columnas].equals("rat")){
JLabel rat2 = new JLabel();
rat2.setSize(1270/cc, 750/cc);
rat2.setIcon(new ImageIcon("raton.png"));
compsToExperiment.add(rat2);
}
if (arraystrings[filas][columnas].equals("menjar")){
JLabel comida2 = new JLabel();
comida2.setSize(1270/cc, 750/cc);
comida2.setIcon(new ImageIcon("comida.png"));
compsToExperiment.add(comida2);
}
if (arraystrings[filas][columnas].equals("res")){
JLabel nada2 = new JLabel();
nada2.setSize(1270/cc, 750/cc);
nada2.setIcon(new ImageIcon("nada.png"));
compsToExperiment.add(nada2);
}
}
}
this.repaint();
//compsToExperiment.repaint();
compsToExperiment.setVisible(true);
//this.setVisible(true);
//this.setVisible(false);
}
You need to do custom painting to scale the image to the space available in the grid.
You can try using Darryl's Stretch Icon (or maybe the Shrink Icon).

Grid Layout does not display correctly

I'm trying to build simple calculator gui with display and 9 buttons
public void init()
{
setSize(60,80);
inf = new InfoButton(this);
zero = new CalcButton(this,"0");
one = new CalcButton(this,"1");
add = new CalcButton(this,"+");
sub = new CalcButton(this,"-");
div = new CalcButton(this,"/");
mlt = new CalcButton(this,"*");
modu = new CalcButton(this,"%");
blank = new JButton("");
wys = new Wyswietlacz(); // its JTextPane
wys.setSize(60,20);
przyciski = new JPanel();
przyciski.setSize(60,60);
przyciski.setLayout(new GridLayout(3,3));
przyciski.add(zero);
przyciski.add(one);
przyciski.add(add);
przyciski.add(sub);
przyciski.add(mlt);
przyciski.add(div);
przyciski.add(modu);
przyciski.add(inf);
przyciski.add(blank);
calosc = new JPanel();
calosc.setLayout(new BoxLayout(calosc,BoxLayout.Y_AXIS));
calosc.add(wys);
calosc.add(przyciski);
calosc.setSize(60,80);
add(calosc);
}
and in main i make frame with size (60,80) but when i make it visible all i can see is display and one row of buttons. What am i doing wrong?
Call setPreferredSize(..) instead of setSize() on wys and przyciski. Then use JFrame's pack() instead of specifying a size for it.

How to capture image from webcam WHILST already streaming from webcam too with Java Gstreamer?

I am using the gstreamer library for a Java project that needs to be able to capture an image from a webcam.
I already have the code that displays the webcam stream, I just can't figure out how to capture an image at the press of a button next to it.
I have searched the internet, but could only find pieces of code that show either the stream, or capture the image, but none illustrated both... I've tried to merge those pieces of code, but that didn't work for me either.
What do I have to do to get this to work?
public class WebcamPanel extends JPanel {
private static Pipeline pipe;
public WebcamPanel(){
String[] args = {};
args = Gst.init("Webcam", args);
pipe = new Pipeline("pipeline");
final Element videosrc = ElementFactory.make("dshowvideosrc", "source");
final Element videofilter = ElementFactory.make("capsfilter", "flt");
videofilter.setCaps(Caps.fromString("video/x-raw-yuv, width=320, height=240"));
setLayout(new GridBagLayout());
final GridBagConstraints c = new GridBagConstraints();
JButton takePic = new JButton();
takePic.setPreferredSize(new Dimension(50,50));
c.gridx = 0;
c.insets = new Insets(0,10,0,0);
add(takePic,c);
c.gridx = 2;
c.gridwidth = GridBagConstraints.REMAINDER;
c.insets = new Insets(0,40,0,0);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
VideoComponent videoComponent = new VideoComponent();
Element videosink = videoComponent.getElement();
// This gives 2nd window with stream from webcam
// Element videosink = ElementFactory.make("xvimagesink", "sink");
pipe.addMany(videosrc, videofilter, videosink);
Element.linkMany(videosrc, videofilter, videosink);
videoComponent.setPreferredSize(new Dimension(320, 240));
add(videoComponent,c);
videoComponent.setVisible(true);
// Start the pipeline processing
pipe.setState(State.PLAYING);
}
});
}
}
Have you take a look at camerabin2? This will implement the whole camera workflow for you (viewfinder, image capture, video captue, effects, ...).
The basic approach is to either tee off a 2nd stream and capture selected images from it (e.g. use a valve ! jpegenc ! multifilesink and open the valve for selected images) or to use a output-selector to the image-saving pipe or to use a buffer-probe (hacky).

Categories

Resources