Create a thread to make a function sleep without freezing the program - multithreading

I'm new in QT, I'm trying to create a program that read data from a serial port and create a plot, in that plot a new dot in set every ten seconds, I've used the function QThread::sleep(10); to make the program sleep, but this freeze all the window so i can't close it or doing anything else.
void MainWindow::Reader()
{
//Letura dei dati
serial->waitForReadyRead();
m_readData=serial->QSerialPort::readAll();
//Sgrossatura dei dati
inter=QString(m_readData);
QStringList firstlist2= inter.split("$");
m_readData2=firstlist2.takeFirst();
inter2=QString(m_readData2);
QStringList firstlist3= inter2.split(" ");
m_readData3=firstlist3.takeFirst();
H=m_readData3.toDouble();
QStringList firstlist4=inter2.split(" ");
m_readData4=firstlist4.takeLast();
T=m_readData4.toDouble();
//Ottenere dal timer la variabile tempo
double milli=timer.elapsed();
double sec=milli/1000;
double min=sec/60;
double ore=min/60;
//Creazione dei punti
addPoints(H,T,min);
//Aggiunta dei punti ai grafici
PLOTTER_H();
PLOTTER_T();
//Programma in stand-by per 5 minuti
int a=10000;
QThread::sleep(10); //300
}
Can anybody help me?enter code here

You are using "blocking" operation serial->waitForReadyRead() in gui thread, it will freeze gui thread until serial receives any data. Instead connect QSerialPort::readyRead to slot and read data there. This way you don't need any timers or sleeps at all. If you invoke QThread::sleep() in gui thread event loop freezes - no mouse or keyboard events got recieved all widgets got not responsive.
I'd suggest moving QSerialPort to worker wich runs in separate thread to improve code clarity.

Related

GTK Data Capturing

I’m working in C on a project to capture data from a sensor and display it as part of a GUI application on the Raspberry Pi. I am using GTK 3.0, plus Cairo for graphing. I have built an application that works, but I want to make a modification to enable me to change the frequency of data capture.
Within my main code section I have a command like:-
gdk_threads_add_timeout (250, data_capture, widgets);
This all works, the data capture routine is triggered every 250mS, but I want to add functionality to the GUI to enable the user to change the speed. If I try to call this function from anywhere else other than main, it fails.
I have looked for other ways to do it, but I can’t find any examples or explanations of how I can do it.
Ideally what I would like is something like:-
void update_speed(button, widgets)
// Button to change speed has been pressed
read speed from GUI
update frequency
return
int main()
...
setup GUI
set default speed
start main GTK loop
Does anyone have any idea how I could achieve this?
Edit: Additional Code Snippet
(This is not the whole program, but an extract of main)
int main(int argc, char** argv) {
GtkBuilder *builder;
GtkWidget *window;
GError *err = NULL; // holds any error that occurs within GTK
// instantiate structure, allocating memory for it
struct app_widgets *widgets = g_slice_new(struct app_widgets);
// initialise GTK library and pass it in command line parameters
gtk_init(&argc, &argv);
// build the gui
builder = gtk_builder_new();
gtk_builder_add_from_file (builder, "../Visual/gui/main_window.glade", &err);
window = GTK_WIDGET(gtk_builder_get_object(builder, "main_application_window"));
// build the structure of widget pointers
widgets->w_spn_dataspeed = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "spn_dataspeed"));
widgets->w_spn_refreshspeed = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "spn_refreshspeed"));
widgets->w_adj_dataspeed = GTK_ADJUSTMENT(gtk_builder_get_object(builder, "adj_dataspeed"));
widgets->w_adj_refreshspeed = GTK_ADJUSTMENT(gtk_builder_get_object(builder, "adj_refreshspeed"));
// connect the widgets to the signal handler
gtk_builder_connect_signals(builder, widgets); // note: second parameter points to widgets
g_object_unref(builder);
// Set a timeout running to refresh the screen
gdk_threads_add_timeout(SCREEN_REFRESH_TIMER, (GSourceFunc)screen_timer_exe, (gpointer)widgets);
gdk_threads_add_timeout(DATA_REFRESH_TIMER, (GSourceFunc)data_timer_exe, (gpointer)widgets);
gtk_widget_show(window);
gtk_main();
// free up memory used by widget structure, probably not necessary as OS will
// reclaim memory from application after it exits
g_slice_free(struct app_widgets, widgets);
return (EXIT_SUCCESS);

Unity object respawn keeps it moving

My object and it's clones(with a collider attached) are pooled and deactivated on swipe left or right. When they are activated, they immediateliy move along the direction of swipe. How can possibly set their respawn speed to zero?(horizontal movement)
I would make a script for the objects I wouldn't want to move and either attach it to each individual object or a manager based object which controls the spawned objects. You can simply after instantiating, set their speed variable to 0 and call a coroutine for x seconds and at the end of the coroutine it would change their speed variable back. Make sure each has its own variable for speed as to not affect the whole lot.
It would be something like this..
GameObject clone = (GameObject)Instantiate(prefab, new Vector3(0, 0, 0), Quaternion.identity);
// set speed to zero here.
StartCoroutine(WaitAndMove(2.0F));
And add this function
IEnumerator WaitAndMove(float waitTime) {
yield return new WaitForSeconds(waitTime);
// set speed back here
}

Run 2 UIs on diffrent monitor using qt-creator on Dual-Head Graphics Card

I have a Dual-Display Graphics card, on my system (RHEL 6.3).
I have developed one simple application using qt creator (qt-4.8), which throws two different UIs.
When I execute this then both UIs starts in only one display.
What I need is my one UI should run on primary screen and one on secondary screen (i.e. 0.0 and 0.1).
How should I do this using qt-creator?
xclock -display :0.0
xclock -display :0.1
works fine.
You can use a QDesktopWidget to get screen information. It Allows you to query the amount of screens and the dimension of each one with
int QDesktopWidget::screenCount () const;
const QRect QDesktopWidget::availableGeometry ( int screen = -1 ) const;
From there, you can move your widget to any given screen. For instance, the following code move the widget to a given screen or to the default one if the specified screen is not available:
QDesktopWidget* w = QApplication::desktop();
//some value
int mydesiredscreen = 1;
//fallback to default screen if none
if(mydesiredscreen >= w->screenCount()) mydesiredscreen = -1;
QRect rect1 = w->availableGeometry(mydesiredscreen);
mywindow->move(rect1.topLeft());
Tejas,
To display your Second UI on Secondary Monitor you can use setParent property for your Second UI as :
int screenNumber = 1; /* Desired screen no */
QWidget secondaryUI_widget; /* Secondary UI Object which is to be displayed on secondary monitor */
QDesktopWidget myDesktopWidget; /* Create an object of QDesktopWidget */
secondUI_myDesktopWidget.setParent(myDesktopWidget(screenNumber));
The above line will set the desired screen on which you would like to display your page as parent for your UI object.
Now you can call show() function for your second UI anywhere in your program , the second UI will be displayed on desired screen number as being by screenNumber value

what is the "main" function equivalent in visual c++ (windows form application)?

i have code for getting cursor position in visual c++ (windows form application).
But how do i display it? I used labels but it does not give me a continuously changing cursor position.
My main question is in normal c++ program i wrote the infinite while loop code in "main" function. where do i write it in visual c++ (windows form application) code?
if (!GetCursorPos(&point)) {
this->label4->Text = "An error occurred: ";
//cout << GetLastError();
} else {
x = point.x;
y = point.y;
}
Sleep(1000);
//system("cls");
this->label3->Text = Convert::ToString(x);
this->label4-> Text=Convert::ToString(y);
Instead of an infinite loop to get the cursor position and update the labels, forms offers an event system. So you could figure out the cursor position and update the labels every time, the mouse moves within your application through the mouse move event.
See Control::MouseMove Event for documentation and some examples.

Is a timer mandatory for drawing OPENGL ES

I have a method called startAnimation:
-(void)startAnimation{
1: self.animationTimer=[NSTimer scheduledTimerWithTimeInterval:1/60
target:self selector:#selector(gameLoop)
userInfo:nil repeats:YES];
2: //[self gameLoop]
{
The gameLoop method is like this:
-(void)gameLoop{
[self updateModel];
[self render]
{
Now, a very strange thing happens. If I comment the line 1 and uncomment the line 2 in startAnimation method I will not get the objects rendered to my screen. I thought rendering might require continuously calling the gameLoop metod. But even if I set the timer to not repeat (so repats:NO) objects are drawn. It means calling the gameLoop method just once, but from an NStimer object is enough. But if I call the gameLoop method manually I do not get the objects drawn. I tried calling the method inside a loop which executes 100 times. It did not help either. Is there something special with the timers in regards with OPENGL?Sorry for the question if it's too immature.
It´s been some time since you asked but the problem there is that the time interval is set to 1/60, which is 0 because it´s using the integer division. You should use 1.0/60.0 instead.
A timer is not needed for OpenGL ES. For my drawing app the render method is called everytime the user touches the screen.
However, for games most developers use CADisplayLink to call the render or gameloop method instead of NSTimer, as CADisplayLink will call the render method each time the screen refreshes.
Setting up a CADisplayLink is done like the example below.
- (void)setupDisplayLink {
//this sets up the game loop to be called once each time the screen refreshes
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:#selector(gameLoop:)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
Then the gameLoop should be setup as:
- (void)gameLoop:(CADisplayLink *)displayLink {
[self updateModel];
[self render];
}

Resources