Invalid use of Ui - qt

I'm a student programmer and I'm doing some GUI programing for my company and I have recently ran into an issue that I feel I need some assistance with. Im using Qt and some of its widgets are still confusing to me and the documentation is informative but sometimes confusing to a student(I am hoping that I'm not looking to deep into the issue and overlooking the issue). The build issue I am receiving is in the use of the Ui in the member function checkData. As you might have guessed I am trying to validate data entered into the interface and either display an error message or collect the data. I am using the toDouble function of the class QString to asses the input. The function identifies whether or not the input can be converted by the bool parameter in toDouble(bool &worksornot).
Prior to the conversion toDOuble I take in the text from the lineEdit field perspectivley from the Ui. It seems that this is where my issue is; however according to the documentation this SHOULD work; however should has always been a funny word. The code for my checkData Functions is here:
void InjectionDialog::checkData()
{
bool validateFluidVelocity;
QString tempStrFluidVelocity;
tempStrFluidVelocity = ui->InjectionDialog.lineEditFluidVelocity->text();
double convertedFluidVelocity = tempStrFluidVelocity.toDouble(&validateFluidVelocity);
if (validateFluidVelocity == false)
{
QErrorMessage validateErrorFluidVelocityError;
validateErrorFluidVelocityError.showMessage("Fluid velocity input is invalid");
validateErrorFluidVelocityError.exec();
}
else
{
transData.lineEditFluidVelocity = convertedFluidVelocity;
}
bool validateFluidMassFlow;
QString tempStrFluidMassFlow;
tempStrFluidMassFlow = ui->InjectionDialog.lineEditFluidMassFlow->text();
double convertedFluidMassFlow = tempStrFluidMassFlow.toDouble(&validateFluidMassFlow);
if (validateFluidMassFlow == false)
{
QErrorMessage validateErrorFluidMassFlowError;
validateErrorFluidMassFlowError.showMessage("Fluid mass flow input is invalid");
validateErrorFluidMassFlowError.exec();
}
else
{
transData.lineEditFluidMassFlow = convertedFluidMassFlow;
}
bool validateParticleVelocity;
QString tempStrParticleVelocity;
tempStrParticleVelocity = ui->InjectionDialog.lineEditParticleVelocity->text();
double convertedParticleVelocity = tempStrParticleVelocity.toDouble(&validateParticleVelocity);
if (validateParticleVelocity == false)
{
QErrorMessage validateErrorParticleVelocity;
validateErrorParticleVelocity.showMessage("Particle velocity input is invalid");
validateErrorParticleVelocity.exec();
}
else
{
transData.lineEditParitcleVelocity =convertedParticleVelocity;
}
bool validateParticleMassFlow;
QString tempStrParticleMassFlow;
tempStrParticleMassFlow = ui->InjectionDialog.lineEditParticleMassFlow->text();
double convertedParticleMassFlow = tempStrParticleMassFlow.toDouble(&validateParticleMassFlow);
if (validateParticleMassFlow == false)
{
QErrorMessage validateErrorParticleMassFlow;
validateErrorParticleMassFlow.showMessage("Particle mass flow input is invalid");
validateErrorParticleMassFlow.exec();
}
else
{
transData.lineEditParticleMassFlow = convertedParticleMassFlow;
}
Sorry about the long names; as a student I have found that I need to use alot more description vs abbreviation. Because I'm not sure what the problem is I'm not sure how much of my code is relevant. Please don't leave negative comments or mark this question as unsubstantial. Just let me know what you would like to see and Ill add more. Heres my injectiondialog header:
#ifndef INJECTIONDIALOG_H
#define INJECTIONDIALOG_H
#include "injectiondata.h"
#include <QDialog>
namespace Ui {
class InjectionDialog;
}
class InjectionDialog : public QDialog
{
Q_OBJECT
public:
void setData(InjectionData &name);
explicit InjectionDialog(QWidget *parent = 0);
~InjectionDialog();
private:
InjectionData transData;
Ui::InjectionDialog *ui;
private slots:
void checkData();
void checkFluidVelocity();
};
#endif // INJECTIONDIALOG_H
The exact error I recieve is invlaid use of 'Ui::InjectionDialog' and this occurs on
tempStrFluidVelocity = ui->InjectionDialog.lineEditFluidVelocity->text();
tempStrFluidMassFlow = ui->InjectionDialog.lineEditFluidMassFlow->text();
tempStrParticleVelocity = ui->InjectionDialog.lineEditParticleVelocity->text();
tempStrParticleMassFlow = ui->InjectionDialog.lineEditParticleMassFlow->text();
Thanks in advance for any help you can give me.

You only need to remove the "InjectionDialog" text and dereference the ui elements directly:
tempStrFluidVelocity = ui->lineEditFluidVelocity->text();
tempStrFluidMassFlow = ui->lineEditFluidMassFlow->text();
tempStrParticleVelocity = ui->lineEditParticleVelocity->text();
tempStrParticleMassFlow = ui->lineEditParticleMassFlow->text();

Related

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);

Can’t access public slots from QtScript

I have this class:
class JavaScript : public QObject {
Q_OBJECT
public:
JavaScript();
bool executeFromFile(QString file);
bool enabled;
public slots:
void setEnabled( bool enabled );
bool isEnabled() const;
private:
QScriptEngine engine;
};
The methods are defined like this:
#include "javascript.h"
JavaScript::JavaScript() {
executeFromFile("test.js");
}
bool JavaScript::executeFromFile(QString file) {
QFile scriptFile(file);
if (!scriptFile.open(QIODevice::ReadOnly)) return false;
QTextStream stream(&scriptFile);
QString contents = stream.readAll();
scriptFile.close();
engine.evaluate(contents, file);
return true;
}
void JavaScript::setEnabled( bool enabled ) {
JavaScript::enabled = enabled;
}
bool JavaScript::isEnabled() const {
return enabled;
}
I’m trying to access the public slots previously defined in the header file like the documentation says:
http://doc.qt.digia.com/qt/scripting.html#making-a-c-object-available-to-scripts-written-in-qtscript
The test.js file looks like this, just like the examples of the docs:
var obj = new JavaScript();
obj.setEnabled( true );
print( "obj is enabled: " + obj.isEnabled() );
But i’m not getting anything. It seems it doesn’t find the JavaScript object. What am I missing?
Doing a simple
print(1+1)
works just fine.
EDIT: An example in the qt4 webpage implements Q_PROPERTY. I tried this, but got the same result:
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
EDIT 1: Tried implementing the initializer like this:
// javascript.h:
JavaScript(QObject *parent = 0);
// javascript.cpp:
JavaScript::JavaScript(QObject *parent) : QObject(parent) {}
Still nothing...
EDIT 2: Some examples inherits from QScriptable too:
class JavaScript : public QObject, public QScriptable {}
But that makes no difference either.
You need to create QScriptClass instead of QObject. Qt contains example of how to extend script capabilites in Qt. Take a look on Custom Script Class Example
What I think you are actually missing is adding it to the script engine.
At some point you will have to declare a script engine
QScriptEngine * engine = new QScriptEngine(this);
Then you are going to want to add your object to the engine
JavaScript* js= new JavaScript();
QScriptValue jsobj = engine->newQObject(js);
engine->globalObject().setProperty("JavaScript", jsobj );
I'm by no means an expert but I think there is something else you need to do to say
var obj = new JavaScript();
at that point you probably need to take Kamil's advice and make JavaScript a subclass of QScriptClass

QlineEdit with some default text for which cursor should not be moved?

In QT, a created lineEdit shows a text using the setText() method.
But the cursor is movable for the default text. I want the cursor should not be movable for the default text.
My lineEdit type has been set as password. Hence the default text('Password') is also displayed as '********'. Whenever user types the type has to be changed as password and when there is no text or until the user have not typed any text, the lineEdit should display the plain text 'password'
Any idea to fix the above two issues?
In the constructor put
ui->lineEdit->setPlaceholderText("password");
ui->lineEdit->setReadOnly(1);
And in on_lineEdit_selectionChanged() SLOT, put
ui->lineEdit->setText("");
ui->lineEdit->setEchoMode(QLineEdit::Password);
ui->lineEdit->setReadOnly(0);
I noticed this question has tag pyqt so I'll put an actual answer related to that tag for those actually looking for a python way instead of c++.
self.searchEditText = QtGui.QLineEdit()
self.searchEditText.setPlaceholderText("Search for word")
I managed to do what you want by deriving a class from QLineEdit as per following..
Constructor..
QCustomLineEdit::QCustomLineEdit(QWidget *parent) :
QLineEdit(parent)
{
connect(this, SIGNAL(textChanged(QString)), this, SLOT(onTextChanged(QString)));
connect(this, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(onCursorPositionChanged(int,int)));
setEchoMode(QLineEdit::Password); // Echo mode in your case..
m_echoMode = echoMode(); // Member variable to store original echo mode..
m_placeHolderText = "Password"; // Member variable..
m_isPlaceHolderActive = true; // Member varible..
// Default case..
setPlaceholderText("");
setStyleSheet("QCustomLineEdit{color: gray;}");
setEchoMode(QLineEdit::Normal);
setText(__placeHolderText);
}
Override keyPressEvent..
void QCustomLineEdit::keyPressEvent(QKeyEvent *e)
{
if(m_isPlaceHolderActive)
{
if(e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace)
e->accept();
else
QLineEdit::keyPressEvent(e);
return;
}
QLineEdit::keyPressEvent(e);
}
Cursor position change event..
void QCustomLineEdit::onCursorPositionChanged(int /*oldPos*/, int newPos)
{
if(m_isPlaceHolderActive)
{
if(newPos != 0)
setCursorPosition(0);
}
}
Text change event..
void QCustomLineEdit::onTextChanged(const QString &text)
{
if(m_isPlaceHolderActive)
{
if(text.compare(m_placeHolderText) != 0)
{
m_isPlaceHolderActive = false;
// Remove the 'placeHolderText' from 'text' itself..
QString temp = text;
temp = temp.mid(0, text.lastIndexOf(m_placeHolderText));
setStyleSheet("QCustomLineEdit{color: black;}");
setEchoMode(m_echoMode);
setText(temp);
}
else
{
setEchoMode(QLineEdit::Normal);
setText(m_placeHolderText);
setStyleSheet("QCustomLineEdit{color: gray;}");
setCursorPosition(0);
}
}
else
{
if(text.isEmpty())
{
m_isPlaceHolderActive = true;
setStyleSheet("QCustomLineEdit{color: gray;}");
setEchoMode(QLineEdit::Normal);
setText(m_placeHolderText);
}
}
}
I have written it very hastily to just show you. Test it yourself and feel free to point any mistake(s) or optimization(s). Hope this helps.
For question 1, in Qt 5.0 and higher, setPlaceholderText does what you want. https://codereview.qt-project.org/#change,45326

Call by reference with QVector

I have in an Object an QVector of Coordinates (my type) that I want to transfer to an other Vector ( I validate and than want to use ist ).
Header
bool getVector(QVector<Coordinates> &getCoordinates );
C File
static QVector<Coordinates> current;
int getVector( QVector<Coordinates> &getCoordinates)
{
.... stuff ...
getCoordinates = current;
.... stuff ....
return 0;
}
And I use it like
....
QVector<Coordinates> currentCoordinates;
getVector(currentCoordinates);
currentCoordinates.X // CRASH
The debugger goes to this line where an Live Crash happens
inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
So my how can I fix this? As I can use this to get all the other Variables with this methode.
A likely cause of your problem is that current has not been constructed before getVector is called. Initialization of static objects in C++ is a thorny area, and a frequent source of bugs - for more information, see this question, and the static initialization order fiasco FAQ entry.
A simple solution to this problem is to provide access to current via a function, i.e. replace
static QVector<Coordinates> current;
with
static QVector<Coordinates>& getCurrent()
{
static QVector<Coordinates> current;
return current;
}
Note, however, that the function as written above is not thread-safe. If multiple threads may call getCurrent, then it should be protected with a QMutex.
For gareth and the Forum :
the header:
typedef QVector<Coordinates> VesselCoordinates;
bool (*getVessel)(Charakter forCharakter, Vessel& getVessel,VesselCoordinates &getCoordinates );
later i bind tis function pointer to an static function ( cause this part of my Program will be one day convertet to c)
cpp file lower layer:
static struct {
Charakter currentPlayerVessel;
VesselCoordinates possibility;
}data;
static bool getVessel(Charakter forCharakter, Vessel& getVessel,VesselCoordinates &getCoordinates );
// funktion to bind the funktion pointer to this static funktion so it can be called outside the File
static bool serverNamespace::getVessel(Charakter forCharakter, Vessel& getVessel,VesselCoordinates &getCoordinates )
{
bool retValue= false;
if ( forCharakter == data.currentPlayerVessel){
// TODO abfragen ob die Adresse regestriert ist!
if ((true == minSize()) and ((true == shipsInRow())or (true == shipsInLine())))
{
retValue = true;
Vessel test = (Vessel)data.possibility.size();
getVessel = test;
getCoordinates = data.possibility;
}
}
return retValue;
}
And then i can use this in the upper layer cpp file to get the information i need:
// in an Funktion :
VesselCoordinates currentCoordinates;
currentCoordinates.clear();
Vessel currentVessel;
if (true == basicFleet->getVessel(currentCharakter,currentVessel, currentCoordinates ))
// doing stuff to it
so its worik fine but your idea worked just as fine. Maybe you can see why my idea is also working.
Thank you
elektor

segfault after return 0;

I wrote a program to test my binary tree and when I run it, the program seems to crash (btree.exe has stopped working, Windows is checking for a solution ...).
When I ran it through my debugger and placed the breakpoint on the function I suspect is causing it, destroy_tree(), it seemed to run as expected and returned back to the main function. Main, in turn, returned from the program but then the cursor jumped back to destroy_tree() and looped recusively within itself.
The minimal code sample is below so it can be ran instantly. My compiler is MinGW and my debugger is gdb (I'm using Code::Blocks).
#include <iostream>
using namespace std;
struct node
{
int key_value;
node *left;
node *right;
};
class Btree
{
public:
Btree();
~Btree();
void insert(int key);
void destroy_tree();
private:
node *root;
void destroy_tree(node *leaf);
void insert(int key, node *leaf);
};
Btree::Btree()
{
root = NULL;
}
Btree::~Btree()
{
destroy_tree();
}
void Btree::destroy_tree()
{
destroy_tree(root);
cout<<"tree destroyed\n"<<endl;
}
void Btree::destroy_tree(node *leaf)
{
if(leaf!=NULL)
{
destroy_tree(leaf->left);
destroy_tree(leaf->right);
delete leaf;
}
}
void Btree::insert(int key, node *leaf)
{
if(key < leaf->key_value)
{
if(leaf->left!=NULL)
insert(key, leaf->left);
else
{
leaf->left = new node;
leaf->left->key_value = key;
leaf->left->left = NULL;
leaf->left->right = NULL;
}
}
else if (key >= leaf->key_value)
{
if(leaf->right!=NULL)
insert(key, leaf->right);
else
{
leaf->right = new node;
leaf->right->key_value = key;
leaf->right->left = NULL;
leaf->right->right = NULL;
}
}
}
void Btree::insert(int key)
{
if(root!=NULL)
{
insert(key, root);
}
else
{
root = new node;
root->key_value = key;
root->left = NULL;
root->right = NULL;
}
}
int main()
{
Btree tree;
int i;
tree.insert(1);
tree.destroy_tree();
return 0;
}
As an aside, I'm planning to switch from Code::Blocks built-in debugger to DDD for debugging these problems. I heard DDD can display visually pointers to objects instead of just displaying the pointer's address. Do you think making the switch will help with solving these types of problems (data structure and algorithm problems)?
Your destroy_tree() is called twice, you call it once and then it gets called after the execution leaves main() from the destructor.
You may think it should work anyway, because you check whether leaf!=NULL, but delete does not set the pointer to NULL. So your root is not NULL when destroy_tree() is called for the second time,
Not directly related (or maybe it is) to your problem, but it's good practice to give structs a constructor. For example:
struct node
{
int key_value;
node *left;
node *right;
node( int val ) : key_val( val ), left(NULL), right(NULL) {}
};
If you do this, your code becomes simpler, because you don't need worry about setting the pointers when you create a node, and it is not possible to forget to initialise them.
Regarding DDD, it;'s a fine debugger, but frankly the secret of debugging is to write correct code in the first place, so you don't have to do it. C++ gives you a lot of help in this direction (like the use of constructors), but you have to understand and use the facilities it provides.
Btree::destroy_tree doesn't set 'root' to 0 after successfully nuking the tree. As a result, the destructor class destroy_tree() again and you're trying to destroy already destroyed objects.
That'll be undefined behaviour then :).
Once you destroy the root.
Make sure it is NULL so it does not try to do it again (from the destructor)
void Btree::destroy_tree(node *leaf)
{
if(leaf!=NULL)
{
destroy_tree(leaf->left);
destroy_tree(leaf->right);
delete leaf;
leaf = NULL; // add this line
}
}

Resources