I'm trying to make a shop for my game.
In this shop, there should be 2 scroll pannel : one with your iventory's stuff, the other one with what the dealer sells.
(It 'd like to make it this way)
http://i.stack.imgur.com/5gLUr.jpg
So at first, I tried to put a list in my ScrollPane, but I can't put both image of my weapons and text in those.
So I tried to put a table in my ScrollPane : as long as I have stuff in my inventory, I add cells with the item's texture, another one with the name of the weapon, ...)
But there's no way I found to select the table ...
So I'm a bit confused : if I use a List, I can't put texture and make it look fancy, but with Tables, I can't select the items ...
Have you guys got any ideas of how I should do that ?
Thanks !
EDIT : Here is some code, but no everything since it's pretty ugly !
Table test3 = new Table(skin2);
for(WeaponElement weapon : GameScreen.dataLoader.getWeaponArray()){
Image img = new Image(new Texture(weapon.getIconPath()));
test3.add(img).width(32);
test3.add().width(10);
test3.add(weapon.getName()).align(Align.left).row();
}
panelShop = new ScrollPane(test3, skin2);
panelShop.layout();
So basically, I add all my weapons into my test3 table rows add it into my ScrollPane, but i'd like to make them selectable, with I can do by using lists but if I do so, I can't use anymore tables to make it look great...
What about using Buttons to push? The example below shows a table with one button a row. Use a Button with the text you want to display and add a picture beside it.
Table scrollableTable = new Table(skin);
scrollableTable.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
for(WeaponElement weapon : GameScreen.dataLoader.getWeaponArray()){
final TextButton button = new TextButton(wapon.name, skin, "default");
button.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
// do stuff
});
scrollableTable.add(button).center();
// add a picture
Image img = new Image(new Texture(weapon.getIconPath()));
scrollableTable.add(img).width(32);
// finish a row
scrollableTable.row();
}
Try Tree ui component and use it as table. It is selectable and accepts Actor as node (use Table as row layout).
See com.badlogic.gdx.tests.TestTree (link) example.
Related
I want to make sub Table in a Cell to fill to that cell as a parent.
// Main Table
Table mainTable = new Table();
// Sub Table
Table subTable = new Table();
mainTable.add( ).expand().row(); // cell-1
mainTable.add(subTable).expand().row(); // cell-2
mainTable.add( ).expand().row(); // cell-3
The Code result:
When I make subTable.setFillParent(true), it will fill to mainTable. Ok its well.
But I want to make subTable fill to expand size of the cell-2.
I mean:
How can I make this?
Check LibGDX wiki: https://github.com/libgdx/libgdx/wiki/Table#fill
The fill method causes a widget to be sized to the cell. Like expand,
there are also fillX and fillY methods.
table.add(nameLabel).expand().bottom().fillX();
...
I'm writing a plugin for a miscropy program and have problems with the repaint() method.
short question:
Is there any way to get informed as soon as the repaint of a JPanel was done or synchronize the code with it?
detailed version:
My program can plot a set of data in a xy-chart to a JPanel and show it using jfree.chart; In another part of the programm I have many datasets (~100) that I want to plot and save as images. I've also found a solution, but I really don't like it. The Problem can be reduced to a notification about the paint status of a JPanel.
In the part that shall save all images I have this solution:
PlotSpectrum spectrumWindow = getTheWindow(); //pseudo code...
// some stuff
ti = storage.getImage(channel, slice, frame, position);
spectrumWindow.plotData(false, andor.captureSpectrum(ti.pix), wave,
centerWave, fineGrating, exposureTime,
slitWidth, substractBackground);
spectrumWindow.repaint(); // probably not necessary
sleep(100); // this annoys me...
spectrumWindow.savePlot(path, true, config, null);
spectrumWindow is a JPanel that is also displayed in another window and it all works fine.
BUT I really don't like that sleep(100) in there... without it I'm asking for a repaint but it isn't done till I try to save a "snapshot" of (thats what savePlot is doing...). I know, other Thread and these damn synchronization problems...
With the sleeping I'm just making it unnecessary slow and if I wait not long enough the images are not completly drawn (eg lower half missing)
Is there any way to get informed as soon as the repaint was done? I probably would be also fine with a Listener, better would be a solution with a monitor or sth comparable or a method that is repainting NOW (doesn't exists as far I know?)
The main GUI (include the JPanel spectrumWindow) and the earlier pasted code are running in different Threads.
The probably also important parts of my code are following here. Please excuse if some brackets aren't matching or some variables aren't declared, I removed very much code.
thanks
schetefan24
class PlotSpectrum extends ApplicationFrame // that extends JFrame
{
public void plotData(boolean backgroundGiven, int[] spect, double[] wave_,
double centerWave, boolean fineGrating_, double exposureTime,
double slitWidth, boolean substractBackground)
{
//process data and store internally
replot();
}
private void replot()
{
XYSeries series = new XYSeries("Spectrum");
//add data to series
XYSeriesCollection collection = new XYSeriesCollection(series);
//setting up some labels and such stuff...
JFreeChart chart = ChartFactory.createXYLineChart(
title,
"Wavelength [nm]",
yLabel,
collection,
PlotOrientation.VERTICAL,
false,
false,
false
);
dataPanel.add(new ChartPanel(chart)); // this is contained in a Frame
}
public void savePlot(String path, boolean overWriteAll, HashMap<String,String> config, int[][] addData)
{
File output = new File(path);
//some more stuff, ask overwrite etc
if(image)
{
BufferedImage im = createImage();
String extension = path.substring(path.lastIndexOf(".")+1, path.length());
ImageIO.write(im, extension, output);
} else {
//that is an textexport, works fine
}
}
public BufferedImage createImage()
{
JPanel panel = (JPanel) flipChart.getSelectedComponent();
int w = panel.getWidth();
int h = panel.getHeight();
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bi.createGraphics();
panel.paint(g);
return bi;
}
}
that I want to plot and save as images.
add the data to a non visible panel.
create a BufferedImage of the panel
create an ImageIcon using the Image from above
update a JLabel (that has already been added to the frame) using the setIcon(...) method
the above step should generate a PropertyChange event when the Icon changes. You can use a ProperChangeListener to listen for this event. When you receive the event you can repeat steps 1 - 4.
Check out Screen Image. It will help you create an image of a non-visible component.
Note, you don't really need steps 4-5. I just added them so you have a visual of the plots as they are being processed. If you don't want the visual then maybe you just display text on a JLabel indicating which plot is currently being converted.
I have a class that initiates a table with 3 cells filled like so:
[leftButton] [ImageButton] [rightButton]
ImageButton is created & added to characterSelection array:
Texture characters2 = TrafficGame.res.getTexture("chevy");
characterImageStyle = new ImageButton.ImageButtonStyle();
car = new TextureRegion(characters2, 32, 32);
characterImageStyle.imageUp = new TextureRegionDrawable(new TextureRegion(car));
characterImageChevy = new ImageButton(characterImageStyle);
characterSelection.add(characterImageChevy);
Adding to table when player selection is initiated:
table.add(characterSelection.pop());
Now when the user clicks the left/right button, moveLeft/Right() gets called:
public void moveLeft(){
table.getChildren().get(1).clear();
}
This where I'm stuck. It obviously clears the cell but I have no idea how to add an ImageButton back to it from the array.
Table doesn't support swapping actors into the same cell. Instead of clearing the image button, you should hide it. When you're ready for it to show another image, change its image and show it.
characterImageChevy.hide();
((TextureRegionDrawable)characterImageChevy.getStyle().imageUp).setTexture(...);
characterImageChevy.show();
You can directly change the contents of a Scene2D cell. You can obtain the Cell by asking the table to return Cell for a particular Actor. After that you can clear the Cell and set new Actor for its contents.
// first, grab the Actor that you wish to replace
ImageButton actor = characterImageChevy; // you know where to get it from
// next, take the Cell where it's at
Cell<Table> cell = table.getCell(characterImageChevy);
// remove the actor
cell.clearActor();
// set new Actor
cell.setActor(characterImageChevy);
What I'm trying to do is add a label to follow a slider knob and display the knob's value. I currently have a vertical slider and a label stacked inside a table cell. I'm able to position the label to where the knob is and update it's text correctly but am having a problem while moving the knob.
When I move the knob I can make the label follow it as long as I don't update the text. But if I update the text then the label re-centers itself in the cell till the knob has stopped moving at which point it places itself on the knob.
How do I make it so that the label doesn't reposition while it's updating text?
Here's some sample code of what I have going on:
public class OptionsWindow implements Screen {
private Stage stage;
private Table table;
private Slider slider;
private Label label;
private Skin textSkin = new Skin(Gdx.files.internal("skins/skin.json"),
new TextureAtlas(Gdx.files.internal("skins/text.pack")));
private Skin sliderSkin = new Skin(Gdx.files.internal("skins/skin.json"),
new TextureAtlas(Gdx.files.internal("skins/text.pack")));
private min = 1, max = 2;
#Override
public void show() {
stage = new Stage();
table = new Table();
slider = new Slider(min, max, 0.001f, true, sliderSkin);
label = new Label(""), textSkin);
table.stack(label, slider).height(1000);
table.setFillParent(true);
stage.addActor(table);
Gdx.input.setInputProcessor(stage);
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
label.setY(slider.getValue() - min);
label.setText(slider.getValue());
stage.act();
stage.draw();
}
}
I've done a lot of searching for an answer to this question but have yielded no results. I have also tried placing the label in a container and moving the container while changing the label text, but the same result happens. I'm sure somebody had done this before. It seems like something people would want. Please, any help is welcome.
Never done it before, I always show the amount in a label next to or above the slider to give feedback. But the result you are after gives a nice touch. Did you try adding a ChangeListener to your slider? Everytime the slider changes this would be called. So if you insert the new position and text in there it should be updating correctly.
//Slider has to be "final" for the listener.
final Slider slider = new Slider(0, 10, 1, true, skin);
slider.addListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
label.setY(slider.getValue() - min);
label.setText(slider.getValue());
}
});
This does not need to be in your render method. It's a listener so whenever something happens the listener listens for it will execute.
Ok, so I came up with a work around. It would seem that labels move back to their cell alignment position while updating text. to solve this I simply placed my label in a table with a row on either side like so:
Table subTable = new Table();
subTable.add().row();
subTable.add(label).row();
subTable.add();
Then in render I calculate new height values for the exterior cells and apply them:
float topH, botH;
// Calculate heights
topH = (1 - slider.getPercent()) * parentTable.getHeight();
botH = slider.getPercent() * parentTable.getHeight();
// Apply heights to exterior table cells
subTable.getCells().get(0).height(topH);
subTable.getCells().get(2).height(botH);
// Update label text
label.setText(slider.getValue());
This is just a simple form of what I have. You'll want to take into account the label height to get it to position correctly. Also if you want it to follow with the slider at the slider's set animateDuration, you'll want to use getVisualPercent() instead of getPercent(). However this causes issues when your finger flies out of the cell. For some reason the visual percent is linked to where the slider knob is when your finger leaves the cell, not where it ends up.
My work around for this was to just set the animateDuration to 0.0f and just use getPercent(). If I or someone comes up with a solution to the getVisualPercent() option, then that would be nice to have posted as well.
I've been working on some app's using libgdx & I can't figure out how to position a button via coords.
public void create() {
batch = game.getSpriteBatch();
background = new Texture("data/textures/menuScreen_small.png");
bubbleArray = new Array<Bubble>();
Gdx.input.setInputProcessor(stage);
for (int i = 0; i < 20; i++) {
bubbleArray.add(new Bubble(MathUtils.random(0,
Gdx.graphics.getWidth()), MathUtils.random(0,
Gdx.graphics.getHeight())));
}
table = new Table();
stage.addActor(table);
table.setSize(1280, 720);
table.setPosition(0, 0);
//table.left().top();
// table.debug();
//table.row().minHeight(55).maxHeight(55);
skin = new Skin(Gdx.files.internal("data/ui/uiskin.json"));
/*
* HomeScreen [Button 1]
*/
final TextButton camButton = new TextButton("Camera", skin);
//Add button
table.add(camButton);//.left().expandX().fillX();
camButton.setPosition(0, 0);
//Button Height
//table.row().minHeight(55).maxHeight(55);
//Button Width
//table.row().minWidth(55).maxWidth(55);
In the code above I am trying to position my textButton "camButton" at 0,0 on the screen.
when I start the program it's in the very center of the screen.
If anyone has some guides or tips let me know, I need to learn this stuff.
a small 'fix'
Not exactly a fix; but by removing the table in general solved this problem. By doing this I'm adding it to the stage instead of stage > table > button. Any comments to that?
If you just want to be able to fix buttons to absolute positions like 0,0 there is no need to add the items to a table, just add you button to the stage
TextButton button = new TextButton("Floating Button", skin);
button.setPosition(10, 10);
stage.addActor(button);
Edit
If you still want the controlled positioning that the table provides check out the guide for the table layout it has many good examples Table Layout
If you want to position the table
table.left().bottom();
To position items inside a table
table.add(button).expand().bottom().right();
I had your problem. My requirement for the whole screen or part of the screen was. I solved my problem using WidgetGroup layout.
actor.setPosition(100,200);
yourWidgetGroup.addActor(actor);