Vaadin - Unable to center components - design issue - java

I'm not familiar with css, and unfortunately i dont have much time to investigate this so I've choosen build-in Vaadin ValoTheme.
I have a verticallayout with two objects - label and panel, both components should be centered. This is what i'm trying to archieve:
Unfortunately, after enumorous attempts to make simlar, i got this
My code:
public class SplashScreen extends VerticalLayout implements View {
private static final int PANEL_WIDTH = 320;
private static final int PANEL_HEIGHT = 140;
private static final int BUTTON_WIDTH = 270;
private static final int BUTTON_HEIGHT = 70;
private ComponentHelper componentHelper;
private Panel panel;
private VerticalLayout formLayout;
private Label welcome;
private Button toLoginPage;
public SplashScreen() {
initComponents();
buildSplashView();
}
protected void initComponents() {
componentHelper = ComponentHelper.getInstance();
panel = componentHelper.createPanel("", PANEL_WIDTH, PANEL_HEIGHT);
welcome = componentHelper.createH3Label("Welcome");
formLayout = componentHelper.createVerticalLayout();
toLoginPage = componentHelper.createFriendlyButton("To Login Page", BUTTON_WIDTH, BUTTON_HEIGHT);
toLoginPage.addClickListener(this::redirect);
}
private void buildSplashView() {
addComponent(panel);
addComponent(welcome);
formLayout.addComponent(toLoginPage);
formLayout.setComponentAlignment(toLoginPage, Alignment.MIDDLE_CENTER);
panel.setContent(formLayout);
panel.setStyleName(ValoTheme.PANEL_BORDERLESS);
setComponentAlignment(panel, Alignment.MIDDLE_CENTER);
setHeight(100, Unit.PERCENTAGE);
}
public void redirect(Button.ClickEvent event) {
try {
Thread.sleep(Constants.TRANSITION_TIME_DELAY);
getUI().getNavigator().navigateTo(ViewTokens.SIGNIN);
} catch (InterruptedException e) {
}
}
#Override
public void enter(ViewChangeListener.ViewChangeEvent viewChangeEvent) {
}
}
What i'm doing wrong? I can't fully understand how to design layouts properly( Before asking this question, i read Vaadin Book)
Note: 'componentHelper' intended for object creation with some minimal ValoTheme styling.
Thanks for suggestions
UPDATE: Result of using welcome.setSizeUndefined();
UPDATE 2: modified #qtdzz code to reproduce an issue:
private void buildSplashView() {
addComponent(welcome);
addComponent(text1);
addComponent(panel);
setComponentAlignment(welcome, Alignment.MIDDLE_CENTER);
setComponentAlignment(text1, Alignment.MIDDLE_CENTER);
setComponentAlignment(panel, Alignment.MIDDLE_CENTER);
setSizeFull();
panel.setSizeUndefined();
panel.setContent(formLayout);
welcome.setSizeUndefined();
formLayout.addComponent(toLoginPage);
formLayout.setComponentAlignment(toLoginPage, Alignment.MIDDLE_CENTER);
formLayout.setSizeFull();
}

In my opinion, it will be easier if you put the welcome label inside the formLayout and set alignment for it.
Here is my proposal, hope this help:
private void buildSplashView() {
addComponent(panel);
setComponentAlignment(panel, Alignment.MIDDLE_CENTER);
setSizeFull();
panel.setContent(formLayout);
panel.setStyleName(ValoTheme.PANEL_BORDERLESS);
formLayout.addComponent(welcome);
welcome.setSizeUndefined();
formLayout.addComponent(toLoginPage);
formLayout.setComponentAlignment(toLoginPage, Alignment.MIDDLE_CENTER);
formLayout.setComponentAlignment(welcome, Alignment.MIDDLE_CENTER);
formLayout.setSizeFull();
}
Here is the screenshot for above code:
UPDATE1: Based on your code and according to my understand, one solution could be explained in the following way. If you add "text1", "welcome" and "panel" into it, it will look like the bellow picture:
So to make them align middle center, we need to set expandRatio for "text1" and "panel" to 0.5, and 0 for "welcome". Then make "text1" to be Alignment.BOTTOM_CENTER, "welcome" to be Alignment.MIDDLE_CENTER, "panel" to be Alignment.TOP_CENTER, and the toLoginPage button to be Alignment.TOP_CENTER. Then the view will look like bellow:
Code for above picture:
private void buildSplashView() {
addComponent(text1);
addComponent(welcome);
addComponent(panel);
setComponentAlignment(welcome, Alignment.MIDDLE_CENTER);
setComponentAlignment(text1, Alignment.BOTTOM_CENTER);
setComponentAlignment(panel, Alignment.TOP_CENTER);
setSizeFull();
setExpandRatio(text1,0.5f);
setExpandRatio(panel,0.5f);
panel.setSizeUndefined();
panel.setContent(formLayout);
welcome.setSizeUndefined();
text1.setSizeUndefined();
formLayout.addComponent(toLoginPage);
formLayout.setComponentAlignment(toLoginPage, Alignment.TOP_CENTER);
formLayout.setSizeFull();
}
BTW, I feel that really hard to maintain and understand the solution above (e.g. if you want to add another text, you have to add it between text1 and welcome). My recommend solution is to have one wrapper layout (vertical layout) to wrap all component and set it to be middle_center of the base layout. The solution for this is:
private void buildSplashView() {
wrapperLayout.addComponent(text1);//wrapperLayout is a vertical Layout
wrapperLayout.addComponent(welcome);
wrapperLayout.addComponent(panel);
wrapperLayout.setComponentAlignment(welcome, Alignment.MIDDLE_CENTER);
wrapperLayout.setComponentAlignment(text1, Alignment.MIDDLE_CENTER);
wrapperLayout.setComponentAlignment(panel, Alignment.MIDDLE_CENTER);
addComponent(wrapperLayout);
setComponentAlignment(wrapperLayout, Alignment.MIDDLE_CENTER);
setSizeFull();
panel.setSizeUndefined();
panel.setContent(formLayout);
welcome.setSizeUndefined();
text1.setSizeUndefined();
formLayout.addComponent(toLoginPage);
formLayout.setComponentAlignment(toLoginPage, Alignment.MIDDLE_CENTER);
formLayout.setSizeFull();
}
With this approach, you can add any components into the wrapperLayout, it will be automatically align middle_center.

VerticalLayout outerVLayout = new VerticalLayout();
outerVLayout.setSizeFull();
VerticalLayout innerVLayout = new VerticalLayout();
innerVLayout.setSizeUndefined();
outerVLayout.addComponent(innerVLayout);
outerVLayout.setComponentAlignment(innerVLayout, Alignment.MIDDLE_CENTER);
//add components to this inner vertical layout
innerVLayout.addComponent(label);
//textfields are fine but, in case of a label, remember to do this:
label.setSizeUndefined();
I hope it helps. :-)

Related

How would i add textures to textButtons in libgdx

I'm new to libGDX I've been trying to follow tutorials on how to create buttons and add textures to them however I am really struggling with it. How would I add textures to the continue and back buttons? I only have the png image and a .pack file for the textures
Also if anyone would be able to suggest some ways I can change the font of the labels I have for my buttons e.g. lbl_ip
Any help would be really appreciated.
public class MenuScreen implements Screen {
private Viewport viewport;
private Stage stage;
#SuppressWarnings("unused")
private MainGame game;
private Label lbl_ip;
private Label lbl_name;
private Label lbl_back;
private LabelStyle lbl_style;
private Skin txt_skin;
private TextButtonStyle btn_style;
private TextField txt_ip;
private TextField txt_name;
//private TextField txt_back;
private Button btn_confirm;
private Button btn_back;
public static String ip = "localhost"; // change with user input
public static String name = "Player 1";
public static String back = "<---";
public MenuScreen(MainGame game) {
this.game = game;
viewport = new FitViewport(MainGame.V_WIDTH/6, MainGame.V_HEIGHT/6, new OrthographicCamera());
stage = new Stage(viewport, ((MainGame) game).batch);
lbl_style = new Label.LabelStyle();
lbl_style.font = new BitmapFont();
txt_skin = new Skin(Gdx.files.internal("uiskin.json"));
btn_style = new TextButton.TextButtonStyle();
btn_style.font = new BitmapFont();
Table table = new Table();
table.top();
table.setFillParent(true);
lbl_ip = new Label("please enter an IP address:" , lbl_style);
lbl_name = new Label("enter your name: " , lbl_style);
lbl_back = new Label("Return to Main Menue", lbl_style);
txt_ip = new TextField(ip, txt_skin);
txt_name = new TextField(name, txt_skin);
//txt_back = new TextField(back, txt_skin);
btn_confirm = new TextButton("confirm", btn_style);
btn_back = new TextButton("<--", btn_style);
table.add(lbl_ip).expandX();
table.add(txt_ip).width(200);
table.row();
table.add(lbl_name).expandX();
table.add(txt_name).width(200);
table.row();
//table.add(lbl_back).expandX();
table.add(btn_back);
//table.add(txt_back).width(200);
table.row();
table.add(btn_confirm);
table.row();
stage.addActor(table);
Gdx.input.setInputProcessor(stage);
}
private void buttonHandler() {
if(Gdx.input.isKeyPressed(Input.Keys.ENTER)) {
/*
game.setScreen(new PlayScreen(game));
*/
txt_ip.setTextFieldListener(new TextField.TextFieldListener() {
#Override
public void keyTyped(TextField textField, char c) {
ip = textField.getText();
}
});
txt_name.setTextFieldListener(new TextField.TextFieldListener() {
#Override
public void keyTyped(TextField textField, char c) {
name = textField.getText();
}
});
new MPClient(txt_ip.getText(), txt_name.getText(), game);
dispose();
}
}
#Override
public void show() {
// TODO Auto-generated method stub
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0 , 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.draw();
stage.act(delta);
buttonHandler();
}
#Override
public void dispose() {
stage.dispose();
}
}
You need to use ImageTextButton for that. You need to provide it with ImageTextButtonStyle, which is easy to create (you need to assign its imageUp property, other properties can be null).
As far as label font goes, you need to create a new LabelStyle and assign it a new BitmapFont. An example:
Label lab = new Label("This is the text", new LabelStyle(myFont, Color.RED));
"myfont" is a BitmapFont.
Here is a real-world example how to create a BitmapFont:
FreeTypeFontGenerator generator;
FreeTypeFontParameter parameter;
generator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/nidsans-webfont.ttf"));
parameter = new FreeTypeFontParameter();
parameter.size = 12;
parameter.minFilter = TextureFilter.Linear;
parameter.magFilter = TextureFilter.Linear;
myfont = generator.generateFont(parameter);
You need to change the -style- associated with the widget. And you may want to make a new style per widget rather than sharing a style across all (because that would update all widgets with the new background)
LabelStyle newLabelStyle = new LabelStyle(originalLabel.getStyle());
tobeChangedLabel.setStyle(newLabelStyle);
newLabelStyle.background = new Image( //however you like to make the image
Changing the font is somewhat tricky... as the fonts are baked into the style as bitmaps (for rendering speed). You may find that given you don't like the background of your style, or even the font, that you might want to use a different skin. You can make your own or use one from here.
https://github.com/czyzby/gdx-skins
If you have to dynamically choose font you can dynamically build your bitmaps of rendered fonts with gdx-freetype-font-manager
https://jitpack.io/p/1nt3g3r/gdx-freetype-font-manager

Vaadin - Responsive Columns

I'm new to using Vaadin and have been trying to work out how I can make 2 Components be side by side when at full screen, but then stack on top of each other when the screen is mobile.
My current understanding is that a HorizontalLayout puts things side by side. And a VerticalLayout puts things on top of one another. So how do I go about using the functionality from both?
You need to look into using a different Layout type. Vaadin offers you a CssLayout and CustomLayout as well as the standard Vertical and Horizontal.
My personal favourite at the moment is using a CssLayout and then using a custom CSS Grid to make the components responsive.
Java:
#StyleSheet("MyStyleSheet.css")
public class ResponsiveLayout extends CssLayout {
private static final long serialVersionUID = -1028520275448675976L;
private static final String RESPONSIVE_LAYOUT = "responsive-layout";
private static final String LABEL_ONE = "label-one";
private static final String LABEL_TWO = "label-two";
private Label labelOne = new Label();
private Label labelTwo = new Label();
public ResponsiveLayout() {
config();
addComponents(labelOne, labelTwo);
}
private void config() {
addStyleName(RESPONSIVE_LAYOUT);
labelOne.addStyleName(LABEL_ONE);
labelTwo.addStyleName(LABEL_TWO);
}
}
CSS:
.responsive-layout {
display: grid !important;
grid-template-rows: auto;
grid-template-columns: 1fr 1fr;
display: -ms-grid !important; /* IE */
-ms-grid-rows: auto; /* IE */
-ms-grid-columns: 1fr 1fr; /* IE */
}
.label-one {
grid-column: 1;
-ms-grid-column: 1; /* IE */
}
.label-two {
grid-column: 2;
-ms-grid-column: 2; /* IE */
}
#media all and (max-width : 992px) {
.responsive-layout {
grid-template-columns: 1fr;
-ms-grid-columns: 1fr; /* IE */
}
.label-one {
grid-column: 1;
-ms-grid-column: 1; /* IE */
}
.label-two {
grid-column: 1;
-ms-grid-column: 1; /* IE */
}
}
You can use a Vaadin Add-on responsive layout. Using the grid system of flexboxgrid
#Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
ResponsiveLayout responsiveLayout = new ResponsiveLayout();
responsiveLayout.setSizeFull();
ResponsiveRow rowOne = responsiveLayout.addRow();
Button deleteButton = new Button("", VaadinIcons.TRASH);
deleteButton.addStyleName(ValoTheme.BUTTON_DANGER);
deleteButton.setSizeFull();
Button commentButton = new Button("",VaadinIcons.COMMENT);
commentButton.addStyleName(ValoTheme.BUTTON_PRIMARY);
commentButton.setSizeFull();
Button editButton = new Button("", VaadinIcons.EDIT);
editButton.addStyleName(ValoTheme.BUTTON_FRIENDLY);
editButton.setSizeFull();
rowOne.addColumn().withDisplayRules(12,6,4,4).withComponent(deleteButton);
rowOne.addColumn().withDisplayRules(12,6,4,4).withComponent(commentButton);
rowOne.addColumn().withDisplayRules(12,6,4,4).withComponent(editButton);
ResponsiveRow rowTwo = responsiveLayout.addRow();
Label labelOne = new Label("LABEL 1");
Label labelTwo = new Label("LABEL 2");
rowTwo.addColumn().withDisplayRules(12,6,4,4).withComponent(labelOne);
rowTwo.addColumn().withDisplayRules(12,6,4,4).withComponent(labelTwo);
setSizeFull();
addComponent(responsiveLayout);
}
You can view a basic example here
You can combine your layouts, you might want to put two horizontal layouts within a vertical layout. Think of "boxes within boxes". From there you can fine-tune your layout via css, just analyse the generated HTML.
They had a webinar about layouts some time ago, maybe that helps.

Smooth Panning in ScrollPane Javafx

I have a scrollPane with pannable enabled. When panning with a large image the transformation "lags" behind the mouse making for a "blocky" transformation. Is there a way to fix this? There is not much code that is really relevant here to post if you need more specifics just ask.
I realize this is an old post, but others might need help in this area. What I did to solve this problem is to create a Transition object, and under the interpolate function, set the ScrollPane vValue or hValue equal to itself plus 0.001 depending on how fast you want to pan. vValue and hValue are the viewing locations on the ScrollPane, so basically you're just slowly incrementing what your viewing, so it looks like panning but its not. Here's an example from a project I'm working on where you can "pan" down or up with KeyEvents.
#FXML
ScrollPane scroll;
private Transition down;
private Transition up;
public void initialize(){
this.down = new Transition() {
{
setCycleDuration(Duration.INDEFINITE);
}
#Override
protected void interpolate(double v) {
scroll.setVvalue(scroll.getVvalue()+0.001);
}
};
this.up = new Transition() {
{
setCycleDuration(Duration.INDEFINITE);
}
#Override
protected void interpolate(double v) {
scroll.setVvalue(scroll.getVvalue()-0.001);
}
};
}
#FXML
private void handleKeyPress(KeyEvent event){
if(event.getCode() == KeyCode.S){
down.play();
}
if(event.getCode() == KeyCode.W){
up.play();
}
}
#FXML
private void handleKeyRelease(){
this.down.stop();
this.up.stop();
}

Vaadin problems with UI size and scrollbar

I'm realitively new to vaadin and I'm struggling with this problems for 2 days now and I'm desperate.
I modified the original addressbook example and it was perfect until that point when I had to expand the ContactForm with another controlls.
It's easier to show what i want to achieve.
It would be good if I could scroll on the right, but I cant. I show what i have already maybe some of you will notice my fault. I wont post all of the code, just the necessary parts.
This is where I create the main layout.
public class VaadinKoliUI extends UI {
#Override
protected void init(VaadinRequest request) {
TabSheet tabsheet = new TabSheet();
HorizontalLayout residentalsTab = new ResidentalsUI();
residentalsTab.setSizeFull();
tabsheet.addTab(residentalsTab,"Lakók");
tabsheet.setSizeFull();
setContent(tabsheet);
}
}
public class ResidentalsUI extends HorizontalLayout implements View{
private Grid residentalsList = new Grid();
ResidentalFormTest residentalForm = new ResidentalFormTest(this);
public ResidentalsUI(){
buildLayout();
}
private void buildLayout(){
HorizontalLayout actions = new HorizontalLayout(filter,excelDownload, newResidental);
actions.setWidth("100%");
filter.setWidth("100%");
actions.setExpandRatio(filter, 1);
VerticalLayout left = new VerticalLayout(actions, getResidentalsList());
left.setSizeFull();
getResidentalsList().setSizeFull();
left.setExpandRatio(getResidentalsList(), 1);
HorizontalLayout mainLayout = new HorizontalLayout(left, residentalForm);
mainLayout.setSizeFull();
mainLayout.setExpandRatio(left, 1);
this.setSizeFull();
this.addComponent(mainLayout);
}
}
public class ResidentalFormTest extends Panel{
FormLayout content = new FormLayout();
Button save = new Button("Save", this::save);
//more buttons and controlls
public ResidentalFormTest(ResidentalsUI rUI) {
this.rUI = rUI;
buildLayout();
}
private void buildLayout() {
this.setSizeUndefined();
content.setMargin(true);
HorizontalLayout actions = new HorizontalLayout(save, cancel);
actions.setSpacing(true);
content.addComponents(actions, name, sex, address, email, phoneNumber, major,classYear,neptunCode,
roomNumber, rfidCode,comment,equipment,equipment1,equipment2);
actions.setSizeUndefined();
this.setContent(content);
}
}
So from what I understood yet, I have to use a Panel because the FormLayout is not capable to show a scrollbar. I should set my root to full with .setSizeFull() and the childs to undefined with .setSizeUndefined() so it would be the size of the browser window and if something is bigger it would show a scrollbar.
If I modify the VaadinKoliUI class as the following I have the scrollbar but the ui shrinks.
public class VaadinKoliUI extends UI {
#Override
protected void init(VaadinRequest request) {
TabSheet tabsheet = new TabSheet();
HorizontalLayout residentalsTab = new ResidentalsUI();
residentalsTab.setSizeUndefined();
tabsheet.addTab(residentalsTab,"Lakók");
tabsheet.setSizeFull();
setContent(tabsheet);
}
}
Like this:
And now I don't know what to do.
But if someone has an easier and quicker idea, to make the ContactForm to scrollable please tell me.
Thanks in advance
Balázs
I should set my root to full with .setSizeFull() and the childs to undefined...
In your case you should see the root as being your Panel and the FormLayout as the child. As per the Vaadin book:
Normally, if a panel has undefined size in a direction, as it has by
default vertically, it will fit the size of the content and grow as
the content grows. However, if it has a fixed or percentual size and
its content becomes too big to fit in the content area, a scroll bar
will appear for the particular direction
The image below is a naive attempt at a visual representation:
This being said, from the moment you modified ResidentalFormTest to extend a Panel and set the FormLayout as it's content, in order to make your panel have a scroll:
set the panel size to 100%, in ResidentalFormTest.buildLayout():
this.setSizeFull()
set the content size to undefined so it can "expand" beyond the panel size: in ResidentalFormTest.buildLayout(): content.setSizeUndefined()
To fix the space allocation between the grid and panel I reckon a 3:1 ratio should suffice. in ResidentalsUI.buildLayout():
mainLayout.setExpandRatio(left, 3);
mainLayout.setExpandRatio(residentalForm, 1);
NOTE: At times it may come in handy to inspect (or experiment with changes) the rendered elements' properties, styles, etc. Some browsers (chrome, firefox) have built-in support for such developer tools, accessible through a menu or a keyboard combination such as CTRL+SHIFT+I
I think you should have
VaadinKoliUI.setSizeFull
ResidentalsUI.setSizeFull
ResidentalsUI.residentalsList.setSizeFull
ResidentalFormTest.setSizeFull
ResidentalFormTest.content.setSizeUndefined
ResidentalsUI.left.setSizeFull
I also suggest to eliminate the HorizontalLayout mainLayout in ResidentalsUI since it is a horizontal layout itself (and if possible to rename it since it isn't a UI and remove the implements View since it does not seem a view).
Your expand ratios looks good, here are the classes I would wrote:
public class VaadinKoliUI extends UI {
#Override
protected void init(VaadinRequest request) {
TabSheet tabsheet = new TabSheet();
ResidentalsLayout residentalsTab = new ResidentalsLayout();
residentalsTab.setSizeFull();
tabsheet.addTab(residentalsTab,"Lakók");
tabsheet.setSizeFull();
setContent(tabsheet);
}
public class ResidentalsLayout extends HorizontalLayout {
private Grid residentalsList = new Grid();
ResidentalFormTest residentalForm = new ResidentalFormTest(this);
public ResidentalsLayout(){
buildLayout();
}
private void buildLayout(){
HorizontalLayout actions = new HorizontalLayout(filter,excelDownload, newResidental);
actions.setWidth("100%");
filter.setWidth("100%");
actions.setExpandRatio(filter, 1);
VerticalLayout left = new VerticalLayout(actions, getResidentalsList());
left.setSizeFull();
residentalsList.setSizeFull();
left.setExpandRatio(residentalsList , 1);
addComponents(left, residentalForm);
setExpandRatio(left, 1);
setSizeFull();
}
}
public class ResidentalFormTest extends Panel {
FormLayout content = new FormLayout();
Button save = new Button("Save", this::save);
//more buttons and controlls
public ResidentalFormTest(ResidentalsLayout rUI) {
this.rUI = rUI;
buildLayout();
}
private void buildLayout() {
setSizeFull();
content.setMargin(true);
HorizontalLayout actions = new HorizontalLayout(save, cancel);
actions.setSpacing(true);
content.addComponents(actions, name, sex, address, email, phoneNumber, major,classYear,neptunCode, roomNumber, rfidCode, comment, equipment, equipment1, equipment2);
content.setSizeUndefined();
setContent(content);
}
}
Let me know if it works as expected.

Add scroll bar to Composite which uses GridLayout

I want to add vertical scroll bar to the screen that comes out of the below code. can you please suggest how it can be done?
public class SampleDialog extends TrayDialog {
public SampleDialog(final Shell shell) {
super(shell);
this.shell = shell;
}
#Override
public void create() {
super.create();
}
#Override
protected Control SampleDialog(final Composite parent) {
final GridLayout layout = new GridLayout();
layout.numColumns = 1;
parent.setLayout(layout);
createSampleText(parent);
createSampleCombo(parent);
}
}
where:
org.eclipse.jface.dialogs.TrayDialog;
org.eclipse.swt.layout.GridLayout;
org.eclipse.swt.widgets.Composite;
You can use a ScrolledComposite as the main parent for all your child controls in the dialog.
Some helpful snippets can be found here.

Categories