QProgressDialog does not display immediately - qt

I have a QProgressDialog that I want to display immediately
QProgressDialog *progress = new QProgressDialog("Downloading files...",
"Cancel", 0, 2*selection.size()+1);
progress->setMinimumDuration(0);
progress->setWindowModality(Qt::WindowModal);
progress->setValue(0);
Then I run a for loop with the task and finally assign the maximum value:
for (int i = 1; i < selection.size()+1; ++i)
{
progress->setValue(2*i-1);
if (progress->wasCanceled())
break;
do_half_task();
progress->setValue(2*i);
if (progress->wasCanceled())
break;
do_second_half();
}
progress->setValue(2*selection.size()+1);
But with this code, the dialog window borders appear, transparents without any widgets inside, and only gets filled with the label and progressbar when a full for loop has completed.
I think this is because only after a full loop has completed is that Qt can compute the duration of each step, and check that it will be >0 which I am setting as minimum duration. However, from the docs I see
minimumDuration : int
If set to 0, the dialog is always shown as soon as any progress is set. The default is 4000 milliseconds.
From where I would've expected the dialog to show up immediately in the first loop pass after setting progress->setValue(1).
How can I get my QProgressDialog to appear immediately?

Not sure if this matches for Qt too
but in C# if you run the execution of your code in the same thread like
ProcessBar p = new ProcessBar();
this.Controls.Add(p);
...
for (int i = 0; i < 100; i++) {
p.Value = i;
Thread.Sleep(1);
}
then you have the problem that your Form does not get to the code where it is redrawn.
Maybe try making your execution loop in a nother thread?

When you make the main thread go into a loop, it can't do any event processing until the loop ends and your method returns.
So it can only process all "paint update" requests once you are done.
You can call QCoreApplication::processEvents() inside the loop to allow it to return to event processing for a while.

To show the dialog immediately then just call QProgressDialog::show().

Related

In this code can you please explain what is happening after the draw(n -1) function

#include <stdio.h>
#include <cs50.h>
void draw(int n);
int main(void)
{
int height = get_int("number:");
draw(height);
}
void draw(int n)
{
if(n <= 0)
{
return;
}
draw(n - 1);
for(int i = 0 ; i < n ; i++)
{
printf("#");
}
printf("\n");
}
Iam learing recursion topic, suppose the user input 4 when the compiler completes the if part the value of n is '0' and returning when i debug , but then the for loop starts the value of 'n' becomes '1' and also 'i' doesn't change it constantly 0 why is that iam expected n becomes 0 after the if draw(n - 1) completes.
I will try to make this explanation as simple as I can. First things first, To begin with, when using recursion, you would be noticing the calling of a method within itself with a different argument. In your case it is the draw method.
Now each time, a draw method is called inside another draw method, the outer method(in this case the draw that is called first) stops its flow of execution till the completion of the inner draw.
So when you called draw(4), it ran all the code till it reached line 5 in draw method, and called draw(3). Your for loop of draw(4) is not executed yet. This will continue till draw(1) calls a draw(0). At this stage, draw(0) will return out and the draw(1) will continue its for loop from where it left. So you would find that here n=1, leading to the first print of # and then a new line after it. Once the operation completes in here, it continues with where it left for draw(2). Which is the for loop in draw(2) where the value of n=2. And here it does two print of # and then a new line. This continues.
Now for the question why i is always 0, it is to do with what we call scopes in programming, you can see that each time the i is declared fresh in the loop and assigned a value 0. This means, each time a for loop is hit, the value of i is reinitialised to 0. If you had a global var i out side of your draw method, you would have had the value of i being retained.
I did try my best to put things in as simple form as possible but feel free to let me know if you needed more clarity.

QTableView not scrolling all the way to the bottom

I'm mocking up a table in Qt using QTableView and QStandardItemModel. The table represents events in a log. It should scroll to the bottom so that it can show the most recent event. To be clear, I am mocking up this display, I am not adding elements to the table dynamically.
When I try using either the scrollToBottom method or the scrollTo method, the view is scrolling about 3/4 of the way down, rather than to the actual bottom of the window.
Here's a simplified version of my code:
logModel = new QStandardItemModel(THREADWATCHER_LOG_TABLE_LENGTH, 2, this);
logTable = new QTableView;
for (int i = 0; i < THREADWATCHER_LOG_TABLE_LENGTH; i += 6) {
QString spawnTimeString = QString("[16:09:10:");
int spawnTimeMs = 186 + i * 8; // a pseudo-random choice for the interval between spawns
spawnTimeString.append(QString::number(spawnTimeMs) + "]");
logMessage[i] = new QStandardItem(spawnTimeString + " Thread \"Image Fetcher 0\" was spawned in the image processor ");
logModel->setItem(i, 0, logMessage[i]);
// do the same thing with [i+1], [i+2]...[i+5]
// so that I get six different messages in each iteration of the loop
}
logTable->setModel(logModel);
QModelIndex lastIndex = logMessage[THREADWATCHER_LOG_TABLE_LENGTH - 1]->index();
logTable->scrollTo(lastIndex);
I get exactly the same thing if I call logTable->scrollToBottom() instead of scrolling to the last index.
Things I've tried already:
using a single-shot timer (to ensure events have completed before scrolling)
creating a public method that calls logTable->scrollToBottom(), and having something else call that method after this class's constructor finishes (the logic above is in the constructor)

QT: QGraphicsView not updating from inside loop

I'm trying to draw a picture to the screen repeatedly from inside an infinite loop. When I try to draw the picture to the QGraphicsView, it doesn't update unless I break from the loop. Here is my function with the infinite loop:
void MainWindow::displayNoise() {
QImage noise(WIDTH, HEIGHT, QImage::Format_RGB32);
float t = 0;
while (true) {
// Populate noise
rendered_image = noise;
DisplayQImage(rendered_image);
t += 0.200;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
And here is DisplayQImage():
void MainWindow::DisplayQImage(QImage &i)
{
QPixmap pixmap(QPixmap::fromImage(i));
graphics_scene.addPixmap(pixmap);
graphics_scene.setSceneRect(pixmap.rect());
ui->scene_display->setScene(&graphics_scene);
}
Note that graphics_scene and rendered_image are members of MainWindow. If I insert a break statement after my call to DisplayQImage then the first frame renders, but if I don't exit the displayNoise function then the widget doesn't update. I set up a signal so that when I press N it calls displayNoise, and I know the loop is looping. Why isn't the picture showing?
It is because you are not giving the eventloop time to do it's thing. Your function is being called from the eventloop, and the rendering is called from the same eventloop, because they live in the same thread. So you have two options:
write your code in an asyncronous way, eg. with a QTimer.
manually call the eventloop: https://doc.qt.io/qt-5/qeventloop.html#processEvents
I think the first option is probably the nicest way.

Basic PIC Programming issues

I am writing PIC code in C and encountered the following problems:
When I write my delay as _delay_ms(500), my code doesn't compile, it says it didn't recognize this instruction. I am using MPLAB.
I want to write a program that would count how many time the push button is pressed then return that value and display it using LED's. I know how to display it, but not how to make the program to wait for the push of the push button on the pickit.
main()
{
TRISA=0;//Sets all ports on A to be outputs
TRISB=1;//Sets all ports on B to be inputs
for(;;){
if(PORTBbits.RB0==1){//When the button is pressed the LED is off
PORTAbits.RA1 =0;
count=count+1;
}
else{
PORTAbits.RA1=1;
count = count +1;
}
if (count > 20){//if count =20 aka 20 button presses the LED turns on
PORTAbits.RA0=1;
}
else{
PORTAbits.RA0=0;
}
}
}
There are a few issues:
Assuming you're using a PIC24 or a dsPIC, you need to include libpic30.h
Before you include libpic30.h you need to #define FCY to be your instruction rate so that the delay takes the correct number of cycles. See the comments in the libpic30.h file for details.
The function is __delay_ms not _delay_ms. Note that there are two underscores at the beginning.
The name is all lower case, not Delay_ms as in your comment.
You need to add delay in your code when you detect a key is pressed. As you are saying the _delay_ms(500) is not recognized, You can try something like following:
unsigned char x;
// Just waste a few cycles to create delay
for (x = 0; x < 100; x++)
{
// No operation instruction
Nop();
}
You can create your own delay function with specific number of iterations of this for loop. Measure the exact delay created by this function using a profiler if you need. IMO any arbitrary delay, like say 100 iterations as stated above shall work.

How to read each line of a QPlainTextEdit in Qt?

I want to make a program where I take each line of QPlainTextEdit and send it to a WebView which will load those urls. I don't need to check the URL's because the system makes it like that
http://someurl.com/ + each line of the QPlainTextEdit
I have few ideas which I don't know how to use:
Use a foreach loop which will make its self wait 5 seconds to loop again
Make a QTimer to wait like 5 seconds and tick with an integer and when the integer hits the number of lines it will stop
And all of that will be done on every 4 hours by waiting with another timer.
First of all you need the contents of the QPlainTextEdit. Get them and split them using the new line separator to get a list of QStrings each representing a line.
QString plainTextEditContents = ui->plainTextEdit->toPlainText()
QStringList lines = plainTextEditContents.split("\n");
The easiest way to process the lines is to use a QTimer and store somewhere the current index in the list.
// Start the timer
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(processLine()));
timer->start(5000);
Now the slot is called whenever the timer is triggered. It just gets the current line and you do it whatever you want.
void processLine(){
// This is the current index in the string list. If we have reached the end
// then we stop the timer.
currentIndex ++;
if (currentIndex == lines.count())
{
timer.stop();
currentIndex = 0;
return;
}
QString currentLine = lines[currentIndex];
doSomethingWithTheLine(currentLine);
}
Similarly do the same with the 4h timer.

Resources