JavaFX Stage open on specific Screen - weird behavior - javafx

I open a stage using following code:
ObservableList<Screen> screens = Screen.getScreens();
if(screens.size()>1){
Rectangle2D rec = screens.get(preferredScreen).getVisualBounds();
stage.setX(rec.getMinX());
stage.setY(rec.getMinY());
}
When this is called from a window at primary screen, this works perfectly.
When this is called from a non-primary screen, the stage opens on preferred screen and then jumps to the screen where the mouse is in.
Seems to me being a Windows "feature". What would be the best way get this window to the right screen?

According to the JavaDoc of Screen, you should set the new stage relative to the primary screen, because you only extend your desktop. So you should write something like this:
int preferredScreen = 1;
double offsetX = 0;
double offsetY = 0;
Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
ObservableList<Screen> screens = Screen.getScreens();
if(screens.size()>1){
Rectangle2D rec = screens.get(preferredScreen).getVisualBounds();
// upper left corner of the extended screen
offsetX = rec.getMinX();
offsetY = rec.getMinY();
// set relative to this screen
stage.setX(primaryScreenBounds.getMinX() + offsetX);
stage.setY(primaryScreenBounds.getMinY() + offsetY);
}
Can't test it by myself, I only have one monitor.

Related

Forcing layout change when Stage is resized in JavaFX

I ran into a possible bug in JavaFX, but having short time, I am looking for a workaround.
I have a bunch of windows containing a chart and a toolbar:
public void createGui() {
root = new VBox();
ToolBar toolbar = new ToolBar();
Button btnConfig = new Button(bundle.getString("chartWindow.menu.configure"));
btnConfig.setOnAction(e -> doChartConfig());
toolbar.getItems().addAll(btnConfig);
chartPane = new VBox();
root.getChildren().setAll(toolbar, chartPane);
VBox.setVgrow(chartPane, Priority.ALWAYS);
scene = new Scene(root);
setScene(scene);
updateChart(); // Creates a chart
}
I have to resize them from code. (Tiling the open charts.) The simplified tiling code is:
// bounds is the user available area of the monitors(s)
double windowWidth = bounds.getWidth() / tileRule.columns;
double windowHeight = bounds.getHeight() / tileRule.rows;
int r = 0;
int c = 0;
for (Window w : sel) {
w.setWidth(windowWidth);
w.setHeight(windowHeight);
w.setX(bounds.getMinX() + c * windowWidth);
w.setY(bounds.getMinY() + r * windowHeight);
c++;
if (c >= tileRule.getColumns()) {
c = 0;
r++;
if (r >= tileRule.rows) {
break;
}
}
}
When I do this, the windows are perfectly arranged:
However, as it is visible, some of the windows contents aren't resized with the window (Now, accidentally, they are the last 3, but it is not always the case. Sometimes there are more, and they are not always the last ones.)
It is clearly visible, that the scene is the one that isn't resized with the window.
As soon as I resize the window manually, the controls are layed out well.
I trled a bunch of things to hack this:
Calling the requestLayout method manually
Removing the root element from the scene and adding again
Removing the scene from the stage and adding again
Adding 100 ms delay between the resize operations
binding the root elements width to the window width (minus border size)
None of the above helped. (Yes, not even adding the scene again! It caused the most spectacular result, because the contents are resized to the window size, but with streaching its content.)
Does anyone have any other idea how to hack this bug?
I'm using Java 8u74.

How do I allow a user to smoothly resize elements in Flex 3

I have a Flex 3 app that has elements that a user can add to the main canvas then resize and reposition.
There are 3 key functions I am using for the resize which are as follows:
When the resize begins:
private function startResize(event:MouseEvent):void
{
RESIZE_START_MOUSE_X = event.localX;
RESIZE_START_MOUSE_Y = event.localY;
RESIZE_START_WIDTH = this.width;
RESIZE_START_HEIGHT = this.height;
RESIZE_START_X = this.x;
RESIZE_START_Y = this.y;
RESIZE_BOUND = calculateResizeBound(event);
addEventListener(MouseEvent.MOUSE_MOVE, resizeMouseHandler);
isResizing = true;
}
When the resize is complete:
private function endResize():void
{
RESIZE_START_MOUSE_X = -1;
RESIZE_START_MOUSE_Y = -1;
RESIZE_START_WIDTH = this.width;
RESIZE_START_HEIGHT = this.height;
RESIZE_START_X = -1;
RESIZE_START_Y = -1;
RESIZE_BOUND = '';
removeEventListener(MouseEvent.MOUSE_MOVE, resizeMouseHandler);
isResizing = false;
}
Whilst the user is resizing:
private function resizeMouseHandler(event:MouseEvent):void
{
var deltaX:Number = event.localX - RESIZE_START_MOUSE_X;
var deltaY:Number = event.localY - RESIZE_START_MOUSE_Y;
if (RESIZE_BOUND.indexOf('T') > -1)
//We are fixing the top so move the bottom edge
{
this.height = RESIZE_START_HEIGHT + deltaY;
}
if (RESIZE_BOUND.indexOf('B') > -1)
//We are fixing the bottom so move the top edge
{
this.y = RESIZE_START_Y + deltaY;
this.height = RESIZE_START_HEIGHT - deltaY;
}
if (RESIZE_BOUND.indexOf('L') > -1)
//We are fixing the left so move the right edge
{
this.width = RESIZE_START_WIDTH + deltaX;
}
if (RESIZE_BOUND.indexOf('R') > -1)
//We are fixing the right so move the left edge
{
this.x = RESIZE_START_X + deltaX;
this.width = RESIZE_START_WIDTH - deltaX;
}
}
There is another function referenced in these called calculateResizeBound(). What this does is return a string indicating which edge / corner should remain fixed during the resize. Eg 'TL' means that the top left corner should stay fixed, 'BR' means bottom right, 'L' means just the left edge etc etc
When the resize starts from the 'normal' position, ie the top left corner stays fixed, everything works great. Similarly with the left or top edges fixed. However for the bottom and right cases, I need to reposition the element at the same time as resizing it since all the co-ordinates are calculated from the top left.
The problem that I have is that when it does this, the resize is not smooth, it keeps jumping up and down slightly as you resize it. Not only that but when you resize from the 'normal' edges the cursor position remains fixed relative to the fixed edge / corner however from one of the other edges, you can see it start to drift away from the edge / corner as you resize.
With this kind of thing, it is easy to get the + / - of the different bits of the calculation muddled but since the resize is working in the correct direction each time, I assume I have these correct.
So presumably the problem is coming from the simultaneous moving and resizing but I can't find a work-around for it. Any thoughts / suggestions would be much appreciated
Doug McCune has an awesome Resize wrapper that you can use to resize elements. Then you just need to add a mover on it. See the blog post for code/sample: http://dougmccune.com/blog/2007/08/17/my-360flex-slides-and-code/

HowTo stick QDialog to Screen Borders like Skype do?

A long time ago I tried to find method how to stick QDialog window to screen borders for my small projects like Skype windows do it, but I failed. May be I was looking this code not in the right place, so now I'm looking the solution here, on stack! :)
So, does any one have a deal with some kind of such code, links, samples?
In my opinion, we have to reimplement QDialog moveEvent function, like below, but that code does not working:
void CDialog::moveEvent(QMoveEvent * event) {
QRect wndRect;
int leftTaskbar = 0, rightTaskbar = 0, topTaskbar = 0, bottomTaskbar = 0;
// int top = 0, left = 0, right = 0, bottom = 0;
wndRect = this->frameGeometry();
// Screen resolution
int screenWidth = QApplication::desktop()->width();
int screenHeight = QApplication::desktop()->height();
int wndWidth = wndRect.right() - wndRect.left();
int wndHeight = wndRect.bottom() - wndRect.top();
int posX = event->pos().x();
int posY = event->pos().y();
// Snap to screen border
// Left border
if (posX >= -m_nXOffset + leftTaskbar &&
posX <= leftTaskbar + m_nXOffset) {
//left = leftTaskbar;
this->move(leftTaskbar, posY);
return;
}
// Top border
if (posY >= -m_nYOffset &&
posY <= topTaskbar + m_nYOffset) {
//top = topTaskbar;
this->move(posX, topTaskbar);
return;
}
// Right border
if (posX + wndWidth <= screenWidth - rightTaskbar + m_nXOffset &&
posX + wndWidth >= screenWidth - rightTaskbar - m_nXOffset) {
//right = screenWidth - rightTaskbar - wndWidth;
this->move(screenWidth - rightTaskbar - wndWidth, posY);
return;
}
// Bottom border
if (posY + wndHeight <= screenHeight - bottomTaskbar + m_nYOffset &&
posY + wndHeight >= screenHeight - bottomTaskbar - m_nYOffset) {
//bottom = screenHeight - bottomTaskbar - wndHeight;
this->move(posX, screenHeight - bottomTaskbar - wndHeight);
return;
}
QDialog::moveEvent(event);
}
Thanks.
As you thought you can achieve this in the moveEvent function.
I guess the following code do the trick but since I have nothing to test here I will write some pseudo code:
First get the available screen area:
const QRect screen = QApplication::availableGeometry(this);
// This get the screen rect where you can drag a dialog
Then get the position of your dialog relative to the desktop (if your dialog is a child of an other widget, you need to transform coordinates from widget relative to desktop relative):
const QRect dialog = geometry();
// Do here transformation
Now test if dialog is near screen border
if( abs(dialog.left()-screen.left() < OFFSET )
move(screen.left(), dialog.top();
else if( abs(dialog.top()-screen.top() < OFFSET )
move(dialog.left(), screen.top() )
// etc. for the 2 other cases
Let me know if it works
In the pos property description from the QWidget documentation, there is the following warning about moving a window inside the move event handling method.
Warning: Calling move() or setGeometry() inside moveEvent() can
lead to infinite recursion.
That said, there is no proper way to stick the dialog window inside the screen border.
Note :
The behavior you observed in KDE comes from the Window Manager. Actually, the Window Manager is the one that arranges the application windows (like dialog boxes) to show them on the screen. The KDE Window Manager has an option to make all application windows (called client) stick to the border.

What is the right way to scale a Flex application up to fullscreen?

Fullscreen mode and I have been battling for a while in this Flex application, and I'm coming up short on Google results to end my woes. I have no problem going into fullscreen mode by doing a Application.application.stage.displayState = StageDisplayState.FULL_SCREEN;, but the rest of the content just sits there in the top, left corner at it's original size.
All right, says I, I'll just do a stage.scaleMode = StageScaleMode.SHOW_ALL and make it figure out how to pull this off. And it looks like it does. Except that when you mouse over the individual checkboxes and buttons and various components, they all fidget slightly. Just a slight jump up or down as they resize...on mouse over. Well, this is frustrating, but bearable. I can always just invoke invalidateSize() explicitly for all of them.
But for the comboboxes. The ones at the bottom have their menus go off the bottom of the screen, and when I pop out of fullscreen mode, their drop downs cut off half way. I have no idea how to fix that. Can someone step in here, and put me out of my misery?
What is the right way to scale a Flex application up to fullscreen?
var button:Button = button_fullscreen;
try {
if(stage.displayState == StageDisplayState.FULL_SCREEN) {
Application.application.stage.displayState = StageDisplayState.NORMAL;
button.label = "View Fullscreen Mode";
stage.scaleMode = StageScaleMode.NO_SCALE;
} else {
Application.application.stage.displayState = StageDisplayState.FULL_SCREEN;
button.label = "Exit Fullscreen Mode";
stage.scaleMode = StageScaleMode.SHOW_ALL;
}
invalidateSizes(); // Calls invalidateSize() explicitly on several components.
} catch(error:SecurityError) {
Alert.show("The security settings of your computer prevent this from being displayed in fullscreen.","Error: "+error.name+" #"+error.errorID);
} catch(error:Error) {
Alert.show(error.message,error.name+" #"+error.errorID);
}
Sometimes things go wrong with flex :)
try the following approach
stage.align = StageAlign.TOP_LEFT;
then on resize or added to stage set the scaling manually
private function updateScaling():void
{
if(stage.stageWidth != width || stage.stageHeight != height)
{
var scaling:Number = 1;
if(width>height)
{
scaling = stage.stageWidth / width;
}
else
{
scaling = stage.stageHeight / height;
}
scaleX = scaleY = scaling;
}
}

movie does not start in full screen in flash video player

We have this legacy code of a flash video player that functions well enough but still has some loose ends I need to tighten up. It can do the basic "switch to full screen and back to normal size" stunts, however with one exception.
On the first fresh load of the app, if I switch to full screen mode first, and then click to play the movie, the player would be in full screen, yet the movie itself would remain in it's original size.
//trigger
if (stage.displayState == StageDisplayState.NORMAL) {
stage.addEventListener('fullScreen', procFullScreen);
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.displayState = StageDisplayState.FULL_SCREEN;
//mv:VideoDisplay
mv.percentHeight = 100;
mv.percentWidth = 100;
mv.x = 0;
mv.y = 0;
}
// event handler
if (event.fullScreen) {
mv.smoothing = true;
this.height = stage.height;
this.width = stage.width;
//videoCanvas:Canvas
videoCanvas.height = Application.application.height;
videoCanvas.width = Application.application.width;
fullScreenViewStack.selectedIndex = 1;
}
The VideoDisplay object even returns the expected width/height, but the movie just plays in it's original size. If I switch screen sizes during movie playback, then the movie size will shrink or stretch as it should. I'm running out of ideas, any suggestions? Thanks in advance!
Seems like a bug... What version of sdk are you using?
Have you tried calling validateNow() in the VideoDisplay after switching to fullscreen?

Resources