Hi Want to implement Internationalization concept(for Hindi language) with JavaFx which runs effectively on lower processor.
Configuration :-
Processor - Intel Atom CPUD425# 1.80GHz x 2
RAM - 2 GB
OS - 32 Bit Fedora 15
Implemented Internationalization concept with Resource Bundle. But it is quite slow on that low platform.
And same slowness occurs for English and Hindi Language(2-4sec) though implemented correctly as suggested in How to implement language support for JavaFX in FXML documents?.
So, tried other approach as took one global variable, set that variable to 1 if language changed to Hindi.
And for each fxml controllers initialize method check for
that variable if it is 1 then set fxml label and button text to directly Hindi string as shown below.
#Override
public void initialize(URL location, ResourceBundle resources) {
// TODO Auto-generated method stub
if(Configuration.getLangSelected()==1){
label1.setText("आप क्या करना पसंद करेंगे?");
button1.setText("ई-कैश प्राप्त करें");
button2.setText("सेवा का उपयोग करें");
button3.setText("वापस");
}
}
It improves performance than resource bundle way for low hardware configuration and Flow is fine for English But for Hindi rendering took time(2.8sec).
But 2.8 sec is not accepted here. Is there other way to accomplish this task in minimum time?
For curiousity, As replaced Hindi string with English String in initialization as follows:-
#Override
public void initialize(URL location, ResourceBundle resources) {
// TODO Auto-generated method stub
if(Configuration.getLangSelected()==1){
label1.setText("What you want to do?");
button1.setText("Get E-cash");
button2.setText("Use Service");
button3.setText("Back");
}
}
Same files loaded fast for this change.
Is there any problem as we can not set directly other language string to the labels and buttons such things,
Is there way to set text directly and loading that fxml fastly?
Found work around for this as :- Build separate flow(screens) for hindi with one extra change, use "Text"() inside label. Not setting any text to label. Setting Other language text i.e. Hindi text to that "Text" in fxml. Loading time dropped, Previous time needed :- 2.8 sec, and now 1.2 sec.
Related
I am trying to design a preferences panel for my multidocument app. When a given pref changes – font size, say – all of the document windows should immediately update to reflect the new pref value. I don't want to construct the preferences panel up front, for all the document windows to connect to, because it contains a QFontComboBox that takes more than a second to set itself up (ouch); that's not a price I want to pay at startup. So then, my question is: what is an elegant design for the prefs panel to let all the document windows know about the change? In Cocoa, which I'm more used to, I'd use NSNotification to broadcast a notification from the prefs panel that all the document windows could observe; that provides the loose coupling required (since objects can add themselves as observers before the broadcaster exists).
Two approaches occur to me so far:
Loop through topLevelWidgets, do a dynamic cast to my document window class, and for all the document windows I thereby find, just call a hard-coded method on them directly.
Make a second class, PreferencesNotifier, that is separate from the UI object that takes so long to load, and construct a singleton object of this class at startup that all of the document windows can connect themselves to. When the preferences panel eventually gets created, it can send signals to slots in PreferencesNotifier, which will then call its own signals to notify the connected document windows.
Neither seems quite as elegant as NSNotification, and I'm wondering if I'm missing something. Thanks for any tips.
First thing, do not try to copy patterns, like Cocoa's NSNotification/NotificationCenter, to other frameworks (or languages, or...). There are various ways to send messages and generally each framework has picked one. Trying to use the one method that was picked by the framework you are using will lead to the most elegant solutions.
If you really want to, you could implement your own set of classes that will do exactly what NSNotification does. It will feel more elegant to you, but only because you are used to using Cocoa. It will feel odd to every other Qt developer. Also, this solution will require you to write a lot of code as you will not be able to leverage all the features of Qt.
The first solution you are suggesting is a bit ugly and looks more like a hack than anything.
What I do, when I have to handle preferences in a program, is something similar to your solution 2. I create a class that is responsible for handling all settings: read/write setting file, change setting, set default values, etc. Generally this class is a singleton. This class has very limited access to other parts of the program, and generally no access at all to the UI. Each components that needs to access the preferences will use this class. If you do it properly (e.g. use Q_PROPERTY), this class can even be accessed by QML, if you ever need to use Qt Quick.
class Settings: public QObject {
Q_OBJECT
Q_PROERTY(bool showX READ showX WRITE setShowX NOTIFY showXChanged)
public:
bool showX() const { return m_showX; }
void setShowX(bool show) {
if (show == m_showX)
return;
m_showX = show;
emit showXChanged(m_showX);
}
signals:
void showXChanged(bool);
public slots:
void save() const; // Save to disk
void load(); // Load from disk
private:
QSettings m_settings; // Handle load/save from/to disk
bool m_showX;
};
class Window {
Window() {
...
m_widgetX->setVisible(settings->showX());
connect(settings, &Settings::showXChanged,
this, [this](bool show) { m_widgetX->setVisible(show); }
);
...
}
};
class PrefWindow {
PrefWindow () {
...
ui->checkBoxShowX->setChecked(settings->showX());
...
}
private slots:
void on_saveButton_clicked() {
settings->setShowX(ui->checkBoxShowX->checked()):
settings->save();
}
};
I am using a an object of QScintilla and I am reading the file in QScintilla Object incrementally.
Header myEditor.h
class myScintilla: public QScintilla {
public readFile();
};
#include "myEditor.h"
void myEditor::readFile() {
if (FILE* fp = fopen(ofilename.toLatin1(), "r")) {
QTextStream ts(fp, QIODevice::ReadOnly);
int bufferSize =(1024* 1024)/2;
do {
QString s = ts.read(bufferSize);
append(s);
} while(!ts.atEnd());
}
Even after this change there will be still performance issue while reading large files. It took around
1) 25 seconds to read a file of size 1.5 GB. (Machine cores 4 , 16 GB RAM)
2 10 seconds of file of size 512MB (on same machine)
Is there any way we can load the file in QScintilla object incrementally based on movement of scrollbar?
I found your question interesting so did a little bit of Googling on your behalf. It seems to me that while Scintilla exposes this functionality via the Loader interface, in fact the QScintilla class does not. To make this work, it seems that what you would have to do is use the QScintillaBase class to send the SCI_CREATELOADER message to the Scintilla control.
Edit: Also, you do not want to use append in a loop. That will cause all sorts of terrible things to happen. It will likely force rendering, some sort of indexing, etc. Before using my suggestion above, I would suggest that you instead build up a gigantic QString in memory and then set that at the end. Better to pre-allocate. That might be a little faster.
FINAL ANSWER
Edit #2: OK, it was bothering me that such an industrial strength editor component like Scintilla did not support this natively but it seems that the right way to do this is by using a combination of features:
You start with a document allocated using SCI_ALLOCATE where the number of bytes is the size of your file
You listen for the SCN_UPDATEUI event
Then, based on where the user is scrolling to, you load that data
It should be straightforward to map the above to QScintillaBase as a test.
What is an optimal and an appropriate way to save the state of a Qt GUI so I get the same state I had back when I closed the application ?
By state I mean : current indexes (for combo box ...), color palette, widgets positions... right before closing the application
You can use the QSettings class.
Simple use of QSettings class (code inspired from Qt's documentation):
In the main-window of your application code member functions that saves and restore the settings:
void MainWindow::writeSettings()
{
QSettings settings("reaffer Soft", "reafferApp");
settings.beginGroup("MainWindow");
settings.setValue("size", size());
settings.setValue("pos", pos());
settings.endGroup();
}
void MainWindow::readSettings()
{
QSettings settings("reaffer Soft", "reafferApp");
settings.beginGroup("MainWindow");
resize(settings.value("size", QSize(400, 400)).toSize());
move(settings.value("pos", QPoint(200, 200)).toPoint());
settings.endGroup();
}
Call those 2 functions from the MainWindow constructor and from the closeEvent override, like this:
MainWindow::MainWindow()
{
// code from constructor
//...
readSettings();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
//optional check if the user really want to quit
// and/or if the user want to save settings
writeSettings();
event->accept();
}
The direct answer requires specific elaborated design for your code and not really a short Qt question or even the question specific to Qt. That is about C++ which is not the VM-based language that assists with serializing the state of program code to data. Having all objects serializable we can then attempt to apply certain C++/Qt classes/techniques.
This task is much easier to accomplish with languages like Java, though. And with C++/Qt you have to routinely make serialize-able / serialize / restore everything that is running in your code and still no guarantee that works as long as the context is not fully captured. This task is not easy for sure and makes sense only in specific application.
The most you can get directly from Qt is to save/restore QMainWindow and other independent widgets geometry (position/size):
saveGeometry
restoreGeometry
... and that solution is still somewhat incomplete or you may/not use QSettings for the storage.
I use QSettings for this. With routines similar to Zlatomir's.
For each window I have in the project I use a different section in QSettings and have readSettings() and writeSettings() in the source for each window.
Anything on the form that I want to persist I have to explicitly save and recall. In the case of a QComboBox it would be something like:
QSettings settings("Organisation", "MySoftware");
settings.beginGroup("WindowNumberTwo");
settings.setValue("ComboIndex", combobox->currentIndex());
// save more values here
// ...
settings.endGroup();
I don't know of a built in way to persist your window states - it has to be don't value by value.
I have a viewpager with 3 pages and a fragment (containing inner fragment) on each page. My fragments and the activity communicate directly between each other via saved references (I don’t use interfaces or callback). Also I deactivated rotation, my application is used only in portrait mode so far. I call setOffscreenPageLimit(3) and I never call setRetainInstance().
The application works perfectly when it is launched after being properly destroyed.
But when the application is started after the application was destroyed by the system to recover memory and resources (I do this by pausing my app and launching a few heavy applications), viewpager does not start/attach fragments “normally“ and everything screws up.
I have nullpointerexceptions everywhere. For example, my reference to the activity (saved in onAttach) in a fragment is often null. I used to Runnable to give time but even after 2 seconds, though my traces indicate that all fragment callback functions till onResumed have been called, isAdded() return false and getActivity() return null inside the fragment. Even for the fragment that is supposed to be first displayed. Sometimes some fragments are correctly added.
Of course, the difference between the two scenario above is that in the non-working scenario something happens in onCreate(Bundle) or onRestoreInstanceState(Bundle) . There may be an attempt to reused fragments or whatever. So a workaround is to deactivate the saving of the activity state like that:
#Override
protected void onSaveInstanceState(Bundle outState) {
//super.onSaveInstanceState(outState);
}
This workaround works but I lose the possibility to use onRestoreInstanceState in the future.
If you have run across this issue, what other nicer solutions have you found? Thanks in advance.
I've been coding a simulation in Java and now generate graphs of the results in JavaFX. However, I'm stumped as to how to call the graphs so that when I try to run the simulation (and generate the graphs) for a second time, I don't get the "can't call launch() more than once" error. I read that launch() can only be called once, so what do I need to change to call the graphs successfully on a second run of the simulation?
public class AnswerWorker extends SwingWorker<Void, Integer> {
protected Void doInBackground() throws Exception
{
AMEC.runsimulation();
return null;
}
protected void done()
{
try {
Graphs.launch(Graphs.class, "");
JOptionPane.showMessageDialog(InputGUI.this, AMEC.unsuccesfulpercentage + "% of iterations had trucks that had to sleep over");
AMEC.unsuccesfulpercentage = 0;
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
with a pretty standard graphing class:
public class Graphs extends Application {
#Override public void start(Stage stage) {
....
stage.show();
}
}
Why are you using SwingWorker in a JavaFX application? If your graphs are computed for display in a JavaFX application, there is no reason for you to use the Event Dispatch Thread (AWT). If I'm not mistaken, With the release of JDK 8, the JavaFX Application Thread and the Event Dispatch Thread will become one, so there is no reason (yet) for you to use SwingWorker. If I really am wrong, still, there is no reason for you to use SwingWorker. Although it is possible the coupling of Swing components in JavaFX applications, you should only use EDT when manipulating Swing components, not JavaFX nodes. The following link says this:
...The JavaFX application thread is a different thread from the Swing and AWT Event Dispatch Thread (EDT), so care must be taken when embedding JavaFX code into Swing applications...
Source: http://docs.oracle.com/javafx/2/architecture/jfxpub-architecture.htm
To learn how you can put processes to be done in the background, and also find out which thread is responsible for handling the JavaFX elements, check out this link:
http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm
Regarding your question, I believe the beginning of a JavaFX application should be called only once. So much is, that when a JavaFX application is started, the thread of main method is captured, and is only returned when the JavaFX application is finalized. Just see the Application DOC (Especially this part). Note also that the life cycle of a JavaFX application is given by the following steps:
Life-cycle
The entry point for JavaFX applications is the Application class. The JavaFX runtime does the following, in order, whenever an application is launched:
Constructs an instance of the specified Application class
Calls the init() method
Calls the start(javafx.stage.Stage) method
Waits for the application to finish, which happens when either of
the following occur:
the application calls Platform.exit()
the last window has been closed and the implicitExit attribute on Platform is true
Calls the stop() method
You might be using the wrong approach. I believe that you should leave your JavaFX application running while you're processing something. Once you have processed what you want in the background, you should make your JavaFX application show the results. The way your JavaFX application run while something is being processed in the background is entirely up to you. Maybe you should hide the window while something is processed, and display it again with your chart done. As I said, this is something you will have to decide. I recommend you to take a look at the documentation of classes referring to the window system, starting with Window, and then Stage.
Any questions, we're here. Good Luck! :)
EDIT:
From what I'm seeing, the user jewelsea is right. Apparently it is not certain that the EDT and the JavaFX Application Thread shall become one (it would be quite interesting if that happened). But anyway, be careful not to confuse yourself with the use of both threads.