How to draw dash instead of null in QSpinBox? - qt

I need to draw dash instead of null in QSpinBox. Also I need to make dash key pressing equalling null key pressing.
How can I do this?

You can use setSpecialValueText();
QSpinBox spinBox;
spinBox->setSpecialValueText(tr("-"));
You can then check if the special value is selected by connecting valueChanged(QString) function. Note that this is different from valueChanged(int) You can then check the value of the passed string in a slot, and if it is equal to special text, you can do something.
main()
{
connect(spinBox, SIGNAL(valueChanged(QString)), this, SLOT(doSomething(QString)));
}
void doSomething(QString valueStr)
{
if(valueStr == spinBox->specialValueText())
// Do something
else
//Convert valueStr to int and do other stuff
}
Or you could do something like this:
main()
{
connect(spinBox, SIGNAL(valueChanged()), this, SLOT(doSomething()));
}
void doSomething()
{
if(spinBox->value() == 0)
// Do something with dash
else
//Do something with the value
}
For your other question, you need to create a keyPressEvent and check if pressed key is dash or not. If it's dash you can call another function to do something. Edit: BTW, the index of specialValueText() is 0.
Edit: Or you can create a QShortcut in your main function.
new QShortcut(QKeySequence(Qt::Key_Minus), this, SLOT(doSomething()));
Edit continued: doSomething() is a slot function. Put, for example void doSomething(); in the private slots: section of your header file. And in the cpp file define a function similar to this:
void MainWindow::doSomething()
{
ui->spinBox->setValue(0);
//This is the slot called when you press dash.
}
Edit still continued:
You need to declare a protected: function in the header like this:
virtual void keyPressEvent(QKeyEvent *event);
Then you need to define this function in your cpp file. Like this:
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Minus)
ui->spinBox->setValue(0);
}
You don't have to connect any signals or slots for this function. It's an event.
That means when dash is pressed ui->spinBox->setValue(0);
Because of that, you need to create a spinBox with a range starting from 0.
spinBox->setRange(0, 100);
That means,
if(spinBox->value() == 0)
//Then specialValueText is selected.

Related

How to limit the number of QCheckboxes checked at the same time?

I'm in the process of creating a QT application which is using multiple (14) qcheckboxes. I need to have a limit (preferably set as a variable that i can change) to the number of checkboxes that can be checked at the same time, is there any way to achieve this cleanly ? Thanks for your time.
There is no simple way of doing this, you have to write your code to do it.
I suppose you have the checkboxes in some parent widget class. So I would create a slot which looks like this.
void SomeParentWidget::onCheckBoxToggled(bool value)
{
// when we unchecked the checkbox,
// we do not need to count the number of checked ones
if (!value)
return;
int total = 0;
int limit = 15; // your "magic" number of maximum checked checkboxes
for (auto chb : allCheckBoxes()) // allCheckBoxes() is some method which returns all the checkboxes in consideration
{
if (chb->isChecked())
{
++total;
if (total > limit)
{
// too many checkboxes checked! uncheck the sender checkbox
// Note: you may want to add some nullptr checks or asserts to the following line for better robustness of your code.
qobject_cast<QCheckBox*>(sender())->setChecked(false);
return;
}
}
}
}
And when creating each of your checkboxes inside some parent widget, connect this slot to their signal:
auto chb = new QCheckBox();
connect(chb, &QCheckBox::toggled, this, &SomeParentWidget::onCheckBoxToggled);
Implementation of allCheckBoxes() is up to you, I do not know how you can retrieve the collection of all your check boxes. Depends on your design.
I found another, even simpler solution. Use this slot.
void SomeParentWidget::onCheckBoxToggled(bool value)
{
static int totalChecked = 0; // static! the value is remembered for next invocation
totalChecked += value ? 1 : -1;
Q_ASSERT(totalChecked >= 0);
int maxChecked = 15; // any number you like
if (value && totalChecked > maxChecked)
{
qobject_cast<QCheckBox*>(sender())->setChecked(false);
}
}
... and connect it to checkboxes' toggled() signal. Note that in order to work correctly, all check boxes must be unchecked at the time when you make the signal-slot connection because this function starts counting from zero (0 is the initial value of the static variable).
You can store all your checkboxes in a map (either in an std::map, an std::unordered_map or an QMap). Your keys will be your checkboxes, and your values will be their states, so something like this:
std::unordered_map<QCheckBox*, bool> m_checkBoxStates;
Here's what your connected to your toggled signal of all your checkboxes look like (keep in mind that all the signals will be connected to the same slot):
void MainWindow::onToggled(bool checked) {
QCheckBox* checkBox = sender(); //the checkbox that has been toggled
m_checkBoxStates[checkBox] = checked;
if (!checked) {
return;
}
const int count = std::count_if(m_checkBoxStates.begin(), m_checkBoxStates.end(),
[](const auto pair) {
return pair.second == true;
});
if (count > maxCount) {
checkBox->setChecked(false);
}
}

After I declare an object from a class, and try to set a variable to that object inly, why does it say that it does not declare a type?

I am writing code for a school project that will be used for a Chromebook charging station with security. The problem I am having now is when I am detecting if a Chromebook is actually in the slot after the user has been assigned one, I am using a rocker switch to simulate this but when I am declaring the pin to the rocker, the arduino verfier comes up with that
"'slot1' does not name a type".
Code is below:
//class
class Chromebook_slot {
public:
String Name = "";
String RFID_tag = "";
int rocker = 0;
boolean chromebook_in = false;
//class function to check if chromebook is in.
//if not, redirect already to reassigning so chromebook slot is entered as open and free.
void set_if_in()
{
int momen_1_state = digitalRead(momen_1);
int momen_2_state = digitalRead(momen_2);
// the button has been pushed down and the previous process has been completed
// eg. servos would have been reset if there was a previous user
if (momen_1_state == HIGH || momen_2_state == HIGH)
{
chromebook_in = digitalRead(this->rocker);
if (chromebook_in == 0)
{
re_assigning();
}
else
{
return;
}
}
}
};
//this is now outside the class..
//class declarations
Chromebook_slot slot1;
Chromebook_slot slot2;
//variables for rocker switches which will act for detecting chromebooks.
// in my final version, this will replaced by a photoresistor and laser.
slot1.rocker = 3;
slot2.rocker = 2;
Where the function re_assigning() is a separate function declared further in the code and just resets the slot as open for future use.
slot1.rocker = 3;
slot2.rocker = 2;
These are statements that cannot be at the top level of a C++ (or .ino) file. They need to be inside of a function. What's happening is the compiler is looking looking at the slot1 identifier through the lens of potential valid constructions. It sees an identifier, and about the only thing that could legally exist at this point in the code that starts with an identifier like that is some declaration, e.g. int a = 7;, or more abstractly some_type some_more_stuff. So it expects slot1 to be a type, which it isn't, hence the message.
If you want an assignment like those to happen early on in an Arduino program, the simplest thing you could do is put them in setup():
void setup() {
slot1.rocker = 3;
slot2.rocker = 2;
// ...
}
Or, you'd make these part of the Chromebook_slot's constructor, such that they could be given in slot1 and slot2's declaration:
class Chromebook_slot {
public:
Chromebook_slot(int rocker_init_value) {
rocker = rocker_init_value;
}
// ...
Or in a maybe less familiar but more proper form, using the constructor's initialization list:
class Chromebook_slot {
public:
Chromebook_slot(int rocker_init_value)
: rocker(rocker_init_value) {}
// ...
Once you have a constructor for Chromebook_slot, your variables can become:
Chromebook_slot slot1(3);
Chromebook_slot slot2(2);

Qt -how to get variable value from another function in same file

New to Qt. Still learning it. I have clone.ui, clone.h and clone.cpp. clone ui has 2 buttons.
Browse button-> to Selection a destination path
Add button -> Clone(copy) a file
Clone.h
QString destination_path;
QFileDialog *fdialog;
Clone.cpp has
QFileInfo finfo; // Declare outside function to increase scope
QString destination_name;
void Clone:: on_pushButton__Browse_clicked()
{
/*get the destination path in QString using QFileDialog
Got destination_path */
QString destinatino_path = QFileDialog::getExistingDirectory(....);
QFile finfo(destination_path);
// QFileDialog finfo(destionation_path)
}`
In the same file Clone.cpp
void Clone:: on_btn_Add_clicked()
{
// how to get the same destination_path value here...
//using QFile or some other way?
}
I struck here, Am i missing anything? Any thoughts/suggestion highly useful.
You've create a class (Clone) which has a data member QString destination_path.
Since it is a member variable it has class scope (as in you can access the same variable in any Clone:: member function for the same Clone object).
The problem is that you've hidden it by declaring another QString destination_path in Clone::on_pushButton__Browse_clicked().
void Clone::on_pushButton__Browse_clicked()
{
...
// this *hides* the class member with the same name
QString destination_path = QFileDialog::getExistingDirectory(....);
...
}
The solution is to remove QString from the beginning of the line, which means you are now assigning to the class object's data member.
void Clone::on_pushButton__Browse_clicked()
{
...
// now you're assigning to your object's data member
destination_path = QFileDialog::getExistingDirectory(....);
...
}
Later, in Clone::on_btn_Add_clicked() you can access destination_path, and it will have the value assigned to it in Clone::on_pushButton__Browse_clicked

Qt5 | Function w/ Slot Not Working

I've made an app with two forms.
When I press the save button in the second form, it updates the DB Record, and returns back to the first form. I've connected the two forms via Signal-Slot with this code:
DruckerData.h
signals:
void btnSavePressed(QString printerName);
DruckerData.cpp
UiMainWindow frmMain;
connect(this,SIGNAL(btnSavePressed(QString)),&frmMain,SLOT(refreshSaved( QString )));
emit btnSavePressed(ui->ledit_druckerName->text());
this->hide();
UiMainWindow.h
public slots:
void refreshSaved(QString printerName);
UiMainWindow.cpp
void UiMainWindow::refreshSaved(QString printerName){
qDebug()<<"Updated: "<<printerName;
show_list(); //<<<<<<<<<<<<<<<<<<<<<< this function
}
show_list
void UiMainWindow::show_list (){
QList<DB_Printers_lvs> list;
DB_Printers_lvsTransporter t("LVS");
QString wc;
this->setCursor(Qt::WaitCursor);
wc = QString("where 1=1 order by nam_printer");
if (!t.load_dbPrinters_lvs_wc(&list,wc))
{
log()<< "get printers failed"<< wc << t.getLastError();
this->setCursor(Qt::ArrowCursor);
return;
}
ui.treeWidget->clear();
foreach (DB_Printers_lvs db, list)
{
QTreeWidgetItem *item = new QTreeWidgetItem(0);
printer_to_qtreewidgetitem(item, db);
ui.treeWidget->insertTopLevelItem(ui.treeWidget->topLevelItemCount(), item);
}
ui.treeWidget->header()->resizeSections(QHeaderView::ResizeToContents);
ui.bow_search->apply();
this->setCursor(Qt::ArrowCursor);
}
When I press the button on the second form and the first form shows I see debug writing Updated with printer name but the problem is how can I call or start this funktion show_list()?
Thanks for help.
The problem that you create second instance of UiMainWindow here:
UiMainWindow frmMain;
Then you connect signal with this second instance, call it's slots, but you don't even show this second instance of MainForm. Instead of this, you should connect signal and slot inside the UiMainWindow just after you create DruckerData form. Unfortunatly there is no this code at your question so i can't show exactly place. This should be something like this:
//Inside UiMainWindow
DruckerData *data = new DruckerData(this);
connect(data, SIGNAL(btnSavePressed(QString)),this,SLOT(refreshSaved( QString )));
data->show();

How to Break an Infinite Loop using QPushButton?

I have an infinite loop, inside the loop I want to insert a state whenever I click a button, it will break the current loop.
I've tried several ways like:
if(ui->btnStop->isDown())
{
break;
}
if(ui->btnStop->isChecked())
{
break;
}
and
if(cv::waitKey(10)>=0)
{
break;
}
But, it doesn't work.
I wonder why cv::waitKey doesn't work in Qt, but in a non-Qt project it will work flawlessly.
Are there any other way to break an infinite loop with a QPushButton?
Any help would be appreciated.
It doesn't work because the event processor cannot run whilst execution is locked in your loop. The easiest solution is to simply call QApplication::processEvents() in each loop, this will force the event processor to run.
// Add a boolean to your class, and a slot to set it.
MyClass
{
...
private slots:
void killLoop() { killLoopFlag_ = true; }
private:
bool killLoopFlag_;
}
// In the constructor, connect the button to the slot.
connect( ui->btnStop, SIGNAL( clicked() ),
this, SLOT( killLoop ) );
// Then when performing the loop, force events to be processed and then
// check the flag state.
killLoopFlag_ = false;
while ( true ) {
// ...Do some stuff.
QApplication::processEvents();
if ( killLoopFlag_ ) {
break;
}
}
However you need to ask yourself: Should I be doing long running calculations inside the GUI thread? The answer is usually no.

Resources