I have a simple UI, no animations. Enabling G-SYNC for windowed applications and having focus in the window causes the mouse to be choppy when moving over the whole monitor. FRAPS shows that the window has ~2 fps.
A workaround is to cause repainting. Selecting text or resizing the window increases fps up to the monitor refresh rate (120 fps), which makes the movement look normal.
Using AnimationTimer produces 120fps, but also consumes CPU:
private boolean focus = false;
public void setStageAndSetupListeners(Stage stage) {
stage.focusedProperty().addListener((ov, onHidden, onShown) -> focus = ov.getValue());
AnimationTimer timer = new AnimationTimer() {
#Override
public void handle(long now) {
if (focus) {
label.setVisible(false);
label.setVisible(true);
}
}
};
timer.start();
}
I would like the JavaFX app to behave like any other desktop application - without consuming unnecessary CPU and not being choppy, or at least detect g-sync so that I can enable the workaround.
Win 10, GTX 980Ti, JDK 18
EDIT:
Workaround 2 (bad - font is mangled - screenshot):
-Dprism.order=sw https://stackoverflow.com/a/18773007/685796
Workaround 3 (good - it seems fine):
-Dprism.forceUploadingPainter=true
http://werner.yellowcouch.org/log/javafx-8-command-line-options/
But it is only intended for testing and not recommended for production source
Reported here:
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8289505
Related
I meet two problems, I searched, but they seems not so easy as I think.
I'm working on ubuntu-18.04 with qt-5.15.x. And my two problems are:
cannot restore my window after maximizing it.
cannot move my window out of my screen with mouse dragging
Can not restore
Firstly, I set my window frameless, and then using a button standing for maximize or restoreoperations to trigger maximization or normal
// set fremeless in contruction
setWindowFlags(Qt::FramelessWindowHint | windowFlags());
// maximaization slot or restore
void WindowTitle::onButtonMaxClicked()
{
QWidget *pWin = window();
if(pWin->isMaximized())
{
pWin->showNormal();
}
else
{
pWin->showMaximized();
}
}
What I expected is when I click button ,window will maximized, and that is true indeed. Then clicking on button again, window will return original position and size again, but that doesn't happen, instead, window's height is correct, but its width is equal screen(getting rid of applications docker bar), x-axis value is wrong too. And I have tried setGeometry after I have stored its value, but failed.
Can not move outside
I can make sure that I have set correct position with
void WindowTitle::mouseMoveEvent(QMouseEvent *event)
{
if (m_isPressed)
{
QPoint movePoint = event->globalPos() - m_startMovePos;
QPoint widgetPos = QApplication::activeWindow()->pos();
m_startMovePos = event->globalPos();
QApplication::activeWindow()->move(widgetPos.x() + movePoint.x(), widgetPos.y() + movePoint.y());
}
return QWidget::mouseMoveEvent(event);
}
function, but the result shows something wrong.
I have searched above two questions. But get nothing. And I'm curious that other applications can do just right both restore and move, suchlike Firefox web browser(which I'm typing on). So, there must be some way to make it work.
Hello, People [...]
🤔 Summary
Whenever i use Shadow-effect on my BorderPane or any Component/control/Element, the 3D Graphics performance (as seen, in the Preview section below) is getting way too low.
The "confusing" part is that, it even gets low performance when the effect is applied to something that really has nothing to do with my Tab, Subscene or even my moving Button, in a way [...]
I Use jdk-12.0.1.
👁️ Preview
⚠️ Recreating The Issue
Files Needed:
App.java | main.fxml | AnchorPane.css | MathUtils.java | SimpleFPSCamera.java
📝 General Code
(You can refer to Recreating The Issue Section for more Informations too)
AnchorPane.css
#BorderPane1 {
-fx-effect: dropshadow(three-pass-box, rgb(26, 26, 26), 50, 0.6, 0, 0); /* Comment it*/
}
App.java
public class App extends Application {
#FXML
public Parent root;
public TabPane TabPane1;
public BorderPane BorderPane1;
public static void main(String[] args) throws Exception {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml"));
loader.setController(this);
root = loader.load();
Scene RootScene = new Scene(root, 1120, 540);
primaryStage.setScene(RootScene);
Thread t = new Thread() {
public void run() {
//Setting NewButton2
Button NewButton2 = new Button();
NewButton2.setId("Button2");
NewButton2.setText("test2");
NewButton2.setPrefWidth(150);
NewButton2.setPrefHeight(50);
NewButton2.setTranslateX(-75);
NewButton2.setTranslateY(-25);
NewButton2.setTranslateZ(900);
// Setting group
Group SubRootGroup = new Group(NewButton2);
SubRootGroup.setTranslateX(0);
SubRootGroup.setTranslateY(0);
SubRootGroup.setTranslateZ(0);
// Setting Scene
SubScene SubScene1 = new SubScene(SubRootGroup, 0, 0, true, SceneAntialiasing.BALANCED);
SubScene1.setId("SubScene1");
SubScene1.setFill(Color.WHITE);
SubScene1.heightProperty().bind(RootScene.heightProperty());
SubScene1.widthProperty().bind(RootScene.widthProperty());
// Initializing Camera
SimpleFPSCamera SimpleFPSCam = new SimpleFPSCamera();
// Setting Camera To The Scene
SubScene1.setCamera(SimpleFPSCam.getCamera());
// Adding Scene To Stage-TabPane.Tab(0)
TabPane1.getTabs().add(new Tab("Without Shadows"));
TabPane1.getTabs().get(0).setContent(SubScene1);
// Loading Mouse & Keyboard Events
SimpleFPSCam.loadControlsForSubScene(SubScene1);
}
};
t.setDaemon(true);
t.run();
primaryStage.show();
}
}
Things I 've Tried Until Now
javafx animation poor performance consumes all my cpu
setCache(true);
setCacheShape(true);
setCacheHint(CacheHint.SPEED);
(i have tried using it with all components without having any success [it might be my poor javaFX knowledge too , [using it in the wrong way?] ])
...
💛 Outro
Any Idea? Thanks In Advance, Any help will be highly appreciated, 💛 [...]
George.
Most probably, you will have figured this out by now, but since I was also banging my head about this same issue in the past, here is your answer:
The drop shadow effect is "expensive" and drawing it is slow. If you use it on a node with many descendants and move any of the descendants, it will cause the effect to be re-calculated on the parent, so the whole animation becomes slow (regardless if the parent itself is animated or not).
I solved this by using a StackPane as the top-most container, to which I added a Pane as a first child (which has the css drop-shadow effect) and the normal top-level container for the actual controls as a second child.
This way, the "shadow" pane is not updated when something is animated down the layout tree and, voila, you have a working drop-shadow effect without a performance hit :-)
JavaFX 8 has StageStyle.Unified, enabling to create OS X style, unified toolbars. I have tested the following code works correctly in JDK 8u5.(the scene background is transparent and the button appears against the stage background.)
However in JDK 8u25 and JDK 8u31 there is a weird behavior. the scene background becomes black.
changing the scene color to anything other than transparent works fine, it displays that color.
It is looking like a bug to me unless I am missing something,
Any ideas?
public class UnifiedTest extends Application {
#Override
public void start(Stage primaryStage) {
StackPane testPane = new StackPane();
testPane.setStyle("-fx-background-color:transparent;");
Label someText = new Label("TEXT AGAINST TRANSPARENT SCENE");
testPane.getChildren().add(someText);
Scene myScene = new Scene(testPane,500,500);
myScene.setFill(Color.TRANSPARENT);
primaryStage.setScene(myScene);
primaryStage.initStyle(StageStyle.UNIFIED);
primaryStage.setTitle("Application");
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Some more information:
By stage background I meant the background of the window that is provided by the OS.
I am trying to create a unified toolbar. According to JavaFX 8 API the way to do it is to use StageStyle.UNIFIED. this will give a window provided by the OSX.
It looks like this when there is no scene added:
http://imgur.com/iHEiVf0,fMbFr4e,bFSL8bA
However when I setFill(Color.TRANSPARENT) the scene background becomes black:
http://imgur.com/iHEiVf0,fMbFr4e,bFSL8bA#2
The desired result is to see the text against the background of the first link. It worked with JDK 8u5, but now I am using 8u31 and instead of that grey I get black. What is weird is that if I setFill(Color.RED) the background becomes red as expected
From the JavaFX 8 api:
public static final StageStyle UNIFIED
Defines a Stage style with platform decorations and eliminates the border between client area and decorations. The client area background is unified with the decorations. This is a conditional feature, to check if it is supported see Platform.isSupported(javafx.application.ConditionalFeature). If the feature is not supported by the platform, this style downgrades to StageStyle.DECORATED
` NOTE: To see the effect the Scene covering the Stage should have Color.TRANSPARENT
Looks like this is a bug, which is fixed for Java 8u60:
JDK-8095040 StageStyle.UNIFIED not working on OSX 10.9.5
Kevin Rushforth comments on the bug tracker:
It looks like the regression was introduced some time in 8u20.
I am trying to create a simple video player that just plays a specified video on loop. While the video plays as expected, it does not loop.
The following is the code I am using:
import QtQuick 2.0
import QtMultimedia 5.0
Rectangle
{
width : 320
height : 240
signal buttonPressed(string msg)
property string currentVideo
function playVideo(videoName)
{
currentVideo = videoName
videoPlayer.source = videoName
videoPlayer.seek(1)
videoPlayer.play()
}
function loopVideo()
{
if(videoPlayer.duration === 0)
{
playVideo(currentVideo)
}
}
function stopVideoPlayback()
{
videoPlayer.stop()
}
MediaPlayer {
id: videoPlayer
source: ""
autoPlay: false
autoLoad: false
loops: 100
}
VideoOutput {
id: videoOutput
source: videoPlayer
anchors.fill: parent
visible: true
}
}
I call playVideo from C++. It starts playing as expected. However, once it completes, the frame freezes on the last one. I tried looping it by calling the loopVideo function in a QTimer. That does not work either.
What might I be doing wrong?
Your code is ok. (slight tip: you might want to use MediaPlayer.Infinite instead 100 for looping)
I believe that your situation is same like mine.
I have played a little with MediaPlayer component and at my end I am unable to seek video because seekable is always false. And seekable is false because somehow QML uses my file as live stream, and that results duration property to be 0.
Also note that onPaused and onStopped are never triggered and position is just increasing after end of video (live stream never ends).
Now I think that this is related to looping, because basically looping seeks back to 0. Because there is no duration (MediaPlayer thinks it is live stream) it cannot seek (and loop).
One nasty workaround that I found is this (append to your code):
Rectangle {
id: root
//...
MediaPlayer {
//...
onPositionChanged: {
if (position > VIDEO_LENGTH) {
root.stopVideoPlayback()
root.playVideo(root.currentVideo)
}
}
}
}
Where VIDEO_LENGTH is length of your video file in milliseconds.
Click here for MediaPlayer element documentation
UPDATE:
It looks like that is bug in Qt for mingw version (closed bug report).
UPDATE 2: I have downloaded MSVC version of Qt and media player works as it is supposed.
So it is bug in Qt for mingw.
Either use this workaround (which I wouldn't recommend) or download MSVC version.
I have created new bug report here.
Using stopped signal try this code :
MediaPlayer {
id: mediaplayer
source: "groovy_video.mp4"
onStopped: play()
}
I've created a timer QML app, and I'm using Timer qml component.
The interval is set to 1000 milliseconds (the default one)... but it seems to be working properly only when the app is with focus on it.
When I put it in background it seems that it's not triggered every time, and because of that I got some mistakes in the app.
I've tried to find anything related to that in the documentation, but I couldn't
The timer code is really simple:
Timer {
id: timer
repeat: true
onTriggered: {msRemaining -= 1000; Core.secondsToText(type);}
}
Anyone has any idea about that and how to fix it?
Versions:
Qt 5.2
QML 2.0
OS X 10.9
The QML Timer element is synchronized with the animation timer. Since the animation timer is usually set to 60fps, the resolution of Timer will be at best 16ms. You should also note that in Qt Quick 2 the animation timer is synced to the screen refresh (while in Qt Quick 1 it is hard-coded to 16ms). So when your app runs in background i think the refreshing is stopped and consequently your timer which is synced to screen refresh will stop working properly.
If you want to show elapsed time using a timer as you did is not a good idea because it is not precise. You can use javascript Date() function like:
import QtQuick 2.0
Item {
id: root
width: 200; height: 230
property double startTime: 0
property int secondsElapsed: 0
function restartCounter() {
root.startTime = 0;
}
function timeChanged() {
if(root.startTime==0)
{
root.startTime = new Date().getTime(); //returns the number of milliseconds since the epoch (1970-01-01T00:00:00Z);
}
var currentTime = new Date().getTime();
root.secondsElapsed = (currentTime-startTime)/1000;
}
Timer {
id: elapsedTimer
interval: 1000;
running: true;
repeat: true;
onTriggered: root.timeChanged()
}
Text {
id: counterText
text: root.secondsElapsed
}
}
I have a QML app with a Timer object, running on Android:
With Qt 4.8, the Timer works fine when the QML app is in the background.
With Qt 5.4, the Timer no longer works when the QML app is in the background. For example, the QML app can no longer receive onTriggered() signal. When the QML app is brought back to the foreground again, the Timer starts working again. It appears that the Qt signals are blocked while the QML app is in the background.
So this looks like a regression in Qt. And the best solution would be to wait until this regression is fixed.
This the code snippet working for me, It should inside ApplicationWindow{} or Item{} elements.
Timer{
id: closeTimer
interval: 10000
repeat: true
running: true
onTriggered: {
drawer.close()
}
}
Both repeat and running should be true.