I have a lineEdit I use so the user can enter a frequency interval,
// Making the lineedit objects only accept numbers and align it leftside
ui->frequency->setValidator(new QIntValidator(36, 1000, this));
ui->frequency->setAlignment(Qt::AlignRight);
It works fine to the top limit 1000 but the lower dos not. So I created an slot to control it,
// Control freqeuncy interval
void gui::f_interval()
{
QString f = ui->frequency->text();
freq = f.toInt();
if (freq < 36)
{
int status = QMessageBox::warning(this,"Warning","Invalid frequency interval",QMessageBox::Ok);
}
}
and connected it to the signal of the lineEdit,
// Control frequency interval
connect(ui->frequency, SIGNAL(editingFinished()), this, SLOT(f_interval()));
so that when the user enters a number lower than 36 it gets a warning dialog window.
But it doesn't seem to work. can anyone help me?
You want to connect with textChanged signal instead of editingFinished.
LE: also i don't remember having issues with validator, so can you provide more details, like Qt version, Os version, compiler, maybe see if the issue is reproduced in a sample project.
Related
this is my first time of asking a question in stackoverflow, sorry if my english is not really good. I hope this is a good start.
I am currently trying to use my stm32's key button/ user button (i mean the one button which already included on it in buying written "key") and i want to use the button to do some project. I did some research and found the key button is on pin A0, so i labelled it to BUTTON. So i try to check if the button is functioning using this code:
on private variable section
int a; //variable declare
on while section
while (1){
a = 0
if (HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin)){
a = 1;
} else {
a = 0;
}
}
i'm expecting that when i debug the code and then see the live variable, i will find that variable "a" is gonna turn into 1 when i press the key button, but it is not working as i expected. The variable "a" is still on 0 whatever i do.
im kinda desperate, please help, i appreciate all of the answer :D.
You are setting a = 0; every time around the loop. It might briefly be set to 1 if the button is pressed, but then it will be set back to zero.
Also, the compiler may well detect that the variable a is not actually used for anything, so it might just optimize out the setting of a.
Lastly, HAL_GPIO_ReadPin() can return GPIO_PIN_RESET or GPIO_PIN_SET. So you should test that it is one of those.
Try this:
volatile int a = 0; // Tell compiler not to optimize out setting of 'a'
while (1) {
// No need to set 'a' to zero here
if (HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin) == GPIO_PIN_SET){
a = 1;
} else {
a = 0;
}
}
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().
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.
I'm modifying the Qt 5 Terminal example and use a QTextEdit window as a terminal console. I've encountered several problems.
Qt does a strange interpretation of carriage return ('\r') in incoming strings. Ocassionally, efter 3-7 sends, it interprets ('\r') as new line ('\n'), most annoying. When I finally found out I choose to filter out all '\r' from the incoming data.
Is this behaviour due to some setting?
Getting the cursor interaction to work properly is a bit problematic. I want the console to have autoscroll selectable via a checkbox. I also want it to be possible to select text whenever the console is running, without losing the selection when new data is coming.
Here is my current prinout function, that is a slot connected to a signal emitted as soon as any data has arrived:
void MainWindow::printSerialString(QString& toPrint)
{
static int cursPos=0;
//Set the cursorpos to the position from last printout
QTextCursor c = ui->textEdit_console->textCursor();
c.setPosition(cursPos);
ui->textEdit_console->setTextCursor( c );
ui->textEdit_console->insertPlainText(toPrint);
qDebug()<<"Cursor: " << ui->textEdit_console->textCursor().position();
//Save the old cursorposition, so the user doesn't change it
cursPos= ui->textEdit_console->textCursor().position();
toPrint.clear();
}
I had the problem that if the user clicked around in the console, the cursor would change position and the following incoming data would end up in the wrong place. Issues:
If a section is marked by the user, the marking would get lost when new data is coming.
When "forcing" the pointer like this, it gets a rather ugly autoscroll behaviour that isn't possible to disable.
If the cursor is changed by another part of the program between to printouts, I also have to record that somehow.
The append function which sound like a more logical solution, works fine for appending a whole complete string but displays an erratic behaviour when printing just parts of an incoming string, putting characters and new lines everywhere.
I haven't found a single setting regarding this but there should be one? Setting QTextEdit to "readOnly" doesn't disable the cursor interaction.
3.An idea is to have two cursors in the console. One invisible that is used for printouts and that is not possible at all to manipulate for the user, and one visible which enables the user to select text. But how to do that beats me :) Any related example, FAQ or guide are very appreciated.
I've done a QTextEdit based terminal for SWI-Prolog, pqConsole, with some features, like ANSI coloring sequences (subset) decoding, command history management, multiple insertion points, completion, hinting...
It runs a nonblocking user interface while serving a modal REPL (Read/Eval/Print/Loop), the most common interface for interpreted languages, like Prolog is.
The code it's complicated by the threading issues (on user request, it's possible to have multiple consoles, or multiple threads interacting on the main), but the core it's rather simple. I just keep track of the insertion point(s), and allow the cursor moving around, disabling editing when in output area.
pqConsole it's a shared object (I like such kind of code reuse), but for deployment, a stand-alone program swipl-win is more handy.
Here some selected snippets, the status variables used to control output are promptPosition and fixedPosition.
/** display different cursor where editing available
*/
void ConsoleEdit::onCursorPositionChanged() {
QTextCursor c = textCursor();
set_cursor_tip(c);
if (fixedPosition > c.position()) {
viewport()->setCursor(Qt::OpenHandCursor);
set_editable(false);
clickable_message_line(c, true);
} else {
set_editable(true);
viewport()->setCursor(Qt::IBeamCursor);
}
if (pmatched.size()) {
pmatched.format_both(c);
pmatched = ParenMatching::range();
}
ParenMatching pm(c);
if (pm)
(pmatched = pm.positions).format_both(c, pmatched.bold());
}
/** strict control on keyboard events required
*/
void ConsoleEdit::keyPressEvent(QKeyEvent *event) {
using namespace Qt;
...
bool accept = true, ret = false, down = true, editable = (cp >= fixedPosition);
QString cmd;
switch (k) {
case Key_Space:
if (!on_completion && ctrl && editable) {
compinit2(c);
return;
}
accept = editable;
break;
case Key_Tab:
if (ctrl) {
event->ignore(); // otherwise tab control get lost !
return;
}
if (!on_completion && !ctrl && editable) {
compinit(c);
return;
}
break;
case Key_Backtab:
// otherwise tab control get lost !
event->ignore();
return;
case Key_Home:
if (!ctrl && cp > fixedPosition) {
c.setPosition(fixedPosition, (event->modifiers() & SHIFT) ? c.KeepAnchor : c.MoveAnchor);
setTextCursor(c);
return;
}
case Key_End:
case Key_Left:
case Key_Right:
case Key_PageUp:
case Key_PageDown:
break;
}
you can see that most complexity goes in keyboard management...
/** \brief send text to output
*
* Decode ANSI terminal sequences, to output coloured text.
* Colours encoding are (approx) derived from swipl console.
*/
void ConsoleEdit::user_output(QString text) {
#if defined(Q_OS_WIN)
text.replace("\r\n", "\n");
#endif
QTextCursor c = textCursor();
if (status == wait_input)
c.setPosition(promptPosition);
else {
promptPosition = c.position(); // save for later
c.movePosition(QTextCursor::End);
}
auto instext = [&](QString text) {
c.insertText(text, output_text_fmt);
// Jan requested extension: put messages *above* the prompt location
if (status == wait_input) {
int ltext = text.length();
promptPosition += ltext;
fixedPosition += ltext;
ensureCursorVisible();
}
};
// filter and apply (some) ANSI sequence
int pos = text.indexOf('\x1B');
if (pos >= 0) {
int left = 0;
...
instext(text.mid(pos));
}
else
instext(text);
linkto_message_source();
}
I think you should not use a static variable (like that appearing in your code), but rely instead on QTextCursor interface and some status variable, like I do.
Generally, using a QTextEdit for a feature-rich terminal widget seems to be a bad idea. You'll need to properly handle escape sequences such as cursor movements and color mode settings, somehow stick the edit to the top-left corner of current terminal "page", etc. A better solution could be to inherit QScrollArea and implement all the needed painting–selection-scrolling features yourself.
As a temporary workaround for some of your problems I can suggest using ui->textEdit_console->append(toPrint) instead of insertPlainText(toPrint).
To automatically scroll the edit you can move the cursor to the end with QTextEdit::moveCursor() and call QTextEdit::ensureCursorVisible().
This a very simple problem to which I can find no solution:
This is my code:
qint32 pos = ui->twShow->verticalScrollBar()->value();
ui->twShow->blockSignals(true);
//Code for updating the contents QTableWidget twShow, this is done by erasing all cells and adding them again, in case it matters.
ui->twShow->blockSignals(false);
if (pos > 0){
ui->twShow->verticalScrollBar()->setValue(pos);
}
What I want to accomplish is simply to maintain the vertical scroll position. However the setValue function ignores the value pos (I've checked by printing the value before and after the instruction and both times its cero).
I have also tried:
QScrollBar *bar = ui->twShow->verticalScrollBar();
// Same code as before
ui->twShow->setVerticalScrollBar(bar); //This line crashes de program
However the last line crashes the program (which I've checked by commenting it, and it works fine).
Any advice would be greatly appreciated...
Thank you very much
QTableWidget * tw;
int desiredRow;
// before update
desiredRow = tw->row(tw->itemAt(1,1));
...
// update code
...
tw->scrollToItem( tw->item( desiredRow, 0),
QAbstractItemView::EnsureVisible | QAbstractItemView::PositionAtTop );
QAbstractItemView::EnsureVisible = 0.
The 'or' flag converts the result to an integer which is not allowed as parameter of the scrollToItem method. On the other hand enums are not intended to be used as combined flags.