I have a popup window that is launched with a WxL dimension, where W = width, and L = length.
The content fits well in that area for a few screens. However, in some cases (views that appear conditionally), the window size is not big enough and ends up showing a scrollbar.
The ask here is - How can we auto-adjust the popup window size so that it resizes itself (based on the content), and hence avoid the scrollbar in all cases.
One crude option is to get the max size of all possible views that can appear within the window and always (pre)set that as the size of the window, i.e., something like (W+w)x(L+l). However, that's not ideal/preferable since some of the views do not have much content in them and would look awkward with a larger popup size.
Working demo
$(function(){
$(window).resize(function(){
// get the screen height and width
var maskHeight = $(window).height();
var maskWidth = $(window).width();
// calculate the values for center alignment
var dialogTop = (maskHeight - $('#dialog-box').height())/2;
var dialogLeft = (maskWidth - $('#dialog-box').width())/2;
// assign values to the overlay and dialog box
$('#dialog-overlay').css({ height:$(document).height(), width:$(document).width() }).show();
$('#dialog-box').css({ top: dialogTop, left: dialogLeft, position:"fixed"}).show();
}).resize();
});
Related
I have a Vaadin grid with 7 columns:
Grid grid = new Grid<>();
grid.setSizeFull();
grid.addColumn(User::getUserName).setCaption("Name").setExpandRatio(2);
grid.addColumn(User::getLastName).setCaption("Last Name").setExpandRatio(1);
grid.addColumn(User::getAge).setCaption("Age").setExpandRatio(2);
grid.addColumn(User::getWork).setCaption("Work").setExpandRatio(1);
grid.addColumn(User::getJobTitle).setCaption("Job Title").setExpandRatio(1);
grid.addColumn(User::getSalary).setCaption("Salary").setExpandRatio(1);
grid.addColumn(User::getOther).setCaption("Other").setExpandRatio(1);
What I need is to set columns width in a way - that all 7 will have be shown on a screen.
With my code now it works in a way that if text content of any column cell is very long - the last columns are not shown on the screen and screen must be scrolled horizontally.
I tried to use method setWidth() and as it takes value in pixels the grid view may differ on various browsers and screens.
What I need is to be sure that my grid looks the same way on different screens and with different cell values.
Recently I had the same situation, this was my solution:
Grid configuration
Grid<Item> gridItem = new Grid<>();
gridItem.setRowHeight(50.0);
Column configuration
gridItem.addComponentColumn(item -> {
Label label = new Label();
label.setValue(item.getText());
label.setWidthUndefined();
label.setStyleName(ValoTheme.LAYOUT_HORIZONTAL_WRAPPING);
return label;
})
.setCaption("Item")
.setWidth(380.0);
Result:
I want to create a Card Deck app that contains (lets say) from 0 to 10 total cards as it runs.
I have a RelativeLayout created with XML inside a parent layout, this RelativeLayout has width to match parent and height to wrap content.
Now i want to add fixed size buttons (cards) to that layout and when the don't have room they must not deformate but be scaled and placed on top of the other.
When i just add them it happens this:https://postimg.org/image/ic8pmaju7/
But i want to achieve something like this :https://postimg.org/image/567dj49j9/
*For second image i used setmargins(xleft,x,x,x);...xleft++; , but when i have 2 or 5 buttons they keep being on the top of the other button, instead of just use the free space.
So im asking if there is a layout or a method that when there is no room (small screen or too many buttons) puts buttons on top and next of the other button than deforming them.
ConstraintLayout allows you to create large and complex layouts with a flat view hierarchy (no nested view groups). It's similar to RelativeLayout in that all views are laid out according to relationships between sibling views and the parent layout, but it's more flexible than RelativeLayout and easier to use with Android Studio's Layout Editor.
Using the ConstraintLayout you can do it, and spending less user processing than if you use nested LinearLayouts.
To put button next to button and adjust them in according to screen size, you can use the Chains, that is a resource of ConstraintLayout.
Chains provide group-like behavior in a single axis (horizontally or vertically). The other axis can be constrained independently.
Click here to read more about ConstraintLayout and Click here to read more about Chains.
Ok, guys i tryied what you suggested but i couldnt't achieve what i wanted, so i spent HOURS working on it and i ended up with some math and some help of fuctions to (at last) find the solution. I will post my code if someone wants to give a try:
public void ChangeView(View view) {
//here we put number of cards that we want to be scaled and displayed (cards=buttons)
int CardMax=13;//13 for example!!!
//getting scale for dpi of phone screen(i think??)
final float scale = getResources().getDisplayMetrics().density;
// getting some values we need to know
// **THESE VALUES DEPEND FROM SCREEN RESOLUTION OR THE SIZE OF BUTTON**
int layWidth = layout.getWidth(); //getting layout width that equals screen width(in pixels)
int btnWidth = (int) (50 * scale); //setting and scaling the width of the button for any screen
int maxLayfit=layWidth/btnWidth; //getting how many buttons can be added to layout without deformation
int layMidWidth = layWidth / 2; //getting layouts half width (that helps to start adding buttons from middle)
int StrMeasur; // this help how to start setting the buttons
if (CardMax <= maxLayfit) { // if cards are less than Layout can hold without deformation
StrMeasur = CardMax; // StrMeasur equals number of cards
} else {
StrMeasur = maxLayfit; // else equals max number of cards without deformation
}
int pointer=0; //pointer that will say where to put the first button
pointer = layMidWidth - ((btnWidth / 2) * StrMeasur);//depends of how many cards we have and button width
int start =layMidWidth-((btnWidth / 2) * StrMeasur);
int nextBtn = 0; //nextBtn says where to put the next button
//here we set the buttons on top and next to the previous button as we need **TRICKY PART**
if (CardMax > maxLayfit-1) { //if number of cards is bigger than the number the layout can hold
//then we calculate first card position (start/pointer) and the last card position(=layout width-button width)
//we find how many equal parts the layout has to be divided with the given cards
//and we get the width of the part to set it as pointer of the next card place
nextBtn =(((layWidth-start)-btnWidth)-start)/CardMax;
}else{
nextBtn=btnWidth; //else the pointer just set buttons next to the other
}
//Here we display all the buttons
for (int i = 0; i < CardMax; i++) {
Button cards = new Button(this);
cards.setWidth(btnWidth);
cards.setHeight((int) (90 * scale));
RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params2.setMargins(pointer, 0, 0, 0);
cards.setLayoutParams(params2);
cards.setText("" + (i + 1));
cards.setId(i);
layout.addView(cards);
pointer = pointer + nextBtn;
}
}
I belive it will work on any screen.
I made a grid of buttons in JavaFX.
When I resize the window with the grid inside, the buttons resize within the grid as well.
The problem is that the text on those buttons doesn't resize along with them: it stays the same size all the time, so when the buttons grow big, there's a lot of empty space on a button and then a tiny little text in the middle, which looks terrible.
I would rather like the text to automatically resize along with these buttons to fit the empty space, so that when the entire user interface gets bigger, the text on the buttons gets bigger as well.
How can I accomplish that?
I tried setting the -fx-font-size in the CSS stylesheet to percentage values, but it doesn't seem to work the same way as for websites: the text doesn't scale as a percentage of its container, but as a percentage of some predefined text size.
Edit
This is not a duplicate! Stop marking each question out there as duplicate! If it has been answered, I wouldn't have asked it in the first place!
From what I see, the first of those threads was about a situation where someone wanted to set the size/style of the text for newly-created buttons to account for the current size of their container etc. This is not what I need, because I want the buttons which has been already created as well to automatically resize their texts when these buttons resize inside their container in some way.
The other thread was about scaling the text along with the root container / window with a preset font size. This is also different from what I need, because I don't want the text to be scaled with the window, but with the sizes of the buttons themselves. And it has to be scaled in a certain way: to always fit the size of the button. You know: the text stays the same, but stretches so that it always fits the inside of the button (with a little padding, not a huge empty area around the text).
It is the button's size which is to determine the size of the text on it, not the window or container or something else, and it needs to be done automatically by the button itself (either the built-in one or a subclassed one), not manually by its encompassing container iterating over all these buttons and updating their text's sizes (which would be dumb way to do it).
This is, liked the linked questions, something of a hack: but consider scaling the text node inside the button instead of changing the font size. This seems to work ok:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
public class ScaledButtons extends Application {
#Override
public void start(Stage primaryStage) {
GridPane root = new GridPane();
root.setHgap(5);
root.setVgap(5);
for (int i = 1; i <= 9 ; i++) {
root.add(createScaledButton(Integer.toString(i)), (i-1) % 3, (i-1) / 3);
}
root.add(createScaledButton("#"), 0, 3);
root.add(createScaledButton("0"), 1, 3);
root.add(createScaledButton("*"), 2, 3);
primaryStage.setScene(new Scene(root, 250, 400));
primaryStage.show();
}
private Button createScaledButton(String text) {
Button button = new Button(text);
GridPane.setFillHeight(button, true);
GridPane.setFillWidth(button, true);
GridPane.setHgrow(button, Priority.ALWAYS);
GridPane.setVgrow(button, Priority.ALWAYS);
button.layoutBoundsProperty().addListener((obs, oldBounds, newBounds) ->
scaleButton(button));
button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
return button ;
}
private void scaleButton(Button button) {
double w = button.getWidth();
double h = button.getHeight();
double bw = button.prefWidth(-1);
double bh = button.prefHeight(-1);
if (w == 0 || h == 0 || bw == 0 || bh == 0) return ;
double hScale = w / bw ;
double vScale = h / bw ;
double scale = Math.min(hScale, vScale);
button.lookup(".text").setScaleX(scale);
button.lookup(".text").setScaleY(scale);
}
public static void main(String[] args) {
launch(args);
}
}
An alternate approach to get a similar effect could be to subclass com.sun.javafx.scene.control.skin.ButtonSkin and override the layoutLabelInArea(double x, double y, double w, double h, Pos alignment) method from the skin's parent (LabeledSkinBase). You can then explicitly assign the updated skin to your button (either via CSS or via Java API calls).
Doing so would requires the subclassing of com.sun APIs which could change without notice in subsequent JavaFX releases. Also layoutLabelInArea is reasonably complex in its operation so changing the layout logic could be a little tricky. Certainly, James's suggestion of applying a text rescaling operation based upon a listener to the layout bounds property is simpler in this particular case.
I'm not necessarily advocating this approach, just providing a route to something that you could create that would satisfy your goal of: "It is the button's size which is to determine the size of the text on it, not the window or container or something else, and it needs to be done automatically by the button itself".
I have JTable with two scrollbars (horizontal and vertical). When I use scrollRectToVisible, it return me Rectangle and this action cause that vertical and horizontal scrollbars automatically move to specified rows/columns. How can I move automatically vertical scrollbar to desired place and horizontal scrollbar should stay inactive? This method should show me selected row but my JTable is very wide and I would like to avoid automatically movement (horizontal) at the beginning (left side) of track -> simple say, I expect that horizontal position is unchanged.
public void goToSelected() {
int selectedRow = this.getSelectedRow();
if (selectedRow >= 0)
this.scrollRectToVisible(this.getCellRect(selectedRow, 0, true));
}
The horizontal position might change because you are specifying a column index (0) and the specified column might be invisible. You can simply combine the values of the currently visible area and the cell’s vertical range to get the desired effect:
Rectangle target = getCellRect(selectedRow, 0, true), vis = getVisibleRect();
target.x = vis.x;
target.width = vis.width;
scrollRectToVisible(target);
I have to write app, which can scale font's size of label and buttons depending on size of entire frame. My idea is to increase size of font until whole text fits into label or button.
How can I check is all string fit to button/label?
Something like the following
JComponent c = ... // it can be label, button or any other component
FontMetrics fm = c.getFontMetrics(c.getFont()); // or another font
int strw = fm.stringWidth("My text");
I took this example from Getting string size in java (without having a Graphics object available)