How to end editing QTableWidgetItem - qt

I need to finish edit QTableWidget when some event happend.
MyWindow::onSomeEvent
{
// Finish ui->table editing
//...
}
How can I do this?
The event is a spinbox editing. When it happend rows count becomes equled its value.
I tried to send enter key press event. But when editing item in the last row and new rows count is less then current it does not work.
QKeyEvent *ev = new QKeyEvent(QEvent::KeyRelease,
Qt::Key_Return,
Qt::NoModifier);
QApplication::sendEvent(ui->table, ev);
ui->table->setRowCount(value);
QApplication::sendEvent(ui->table, ev);

Try this:
MyWindow::onSomeEvent()
{
QKeyEvent *ev = new QKeyEvent(QEvent::KeyRelease,Qt::Key_Return,Qt::NoModifier);
QApplication::sendEvent(ui->tableWidget,ev);
}
You just emulate Enter pressing when something happens.

Related

QT Creator, how to 'snap to' a position in tab order following a push button event?

I'm making a form where a user submits their own name, username, etc. but the username must be unique, so it throws up a QMessageBox error if the chosen username is already in use.
If that lineEdit is not first in the tab order, how do you snap to that lineEdit after the click event?
{
UserDB userconn;
QString name,username,password,number,userid,userid2;
name=ui->lineEdit_firstlastname->text();
username=ui->lineEdit_username->text();
password=ui->lineEdit_password->text();
number=ui->lineEdit_phonenumber->text();
userid="Admin";
userid2="User";
QByteArray prehash;
prehash.append(password);
QString hashword = QString(QCryptographicHash::hash(prehash,QCryptographicHash::Md5).toHex());
QSqlQuery qry2;
qry2.prepare("select * from user where username='"+username+"'");
if(qry2.exec())
{
int count=0;
while(qry2.next())\
{
count++;
}
if(count==1)
{
QMessageBox::critical(this,tr("Error!"),tr("Choose a different username!"));
ui->lineEdit_username->setText("");
}
else....
{
/*
here, if the user submits a duplicate username, a
QMessageBox pops up telling the user to choose a
different username, and the focus returns to either the
pushButton or to the last lineEdit before the user
pressed Enter, and in this case, I'd like to return the
focus to that lineEdit that needs to be edited.
*/
}
}
}
What you are looking for is the Qt function setFocus().
Another stackoverflow thread: Set QLineEdit focus in Qt provides different answers on how to use it.

Qt dialog accept and reject

I'm trying to implement the following thing: when a specific button is clicked, a new dialog appears where the user has to enter some information and to check/uncheck some checkboxes. Then the user can either click "OK" or "Cancel".
If he clicks "OK" the information he entered is checked for correctness. If something is not correct the dialog should appear again with a warning message and the user should correct/re-enter the information. I would like the information the user entered to be stored. So, if the information is not correct, the dialog should not "reset" to the initial state but keep the information the user entered.
If the user clicks "Cancel" some standard values are used further.
I almost got a solution, but it is not working properly. When using my solution: when I enter a wrong information and click "OK" a warning appears and the information is stored and I can edit it. But if I enter wrong information again and click "OK" again, then the wrong information is accepted. Please see my code below.
QDialog dialog(this);
QFormLayout form(&dialog);
form.addRow((new QLabel("Please enter the three questions for the P835 test. \n"
"Questions one and two will be permuted, \n "
"question three will not. Below each question enter \n"
"the rating scale starting with the best rating and \n"
"separate the ratings with a comma.")));
QList<QLineEdit *> fields;
QLineEdit *lineEdit_Q1 = new QLineEdit(&dialog);
lineEdit_Q1->setText("Bitte bewerten Sie die Signalqualität!");
QString label_Q1 = QString("First question:");
form.addRow(label_Q1, lineEdit_Q1);
fields << lineEdit_Q1;
QLineEdit *lineEdit_Q1_answer = new QLineEdit(&dialog);
lineEdit_Q1_answer->setText("nicht verzerrt, leicht verzerrt, etwas verzerrt, ziemlich verzerrt, sehr verzerrt");
QString label_Q1_answer = QString("Rating first question:");
form.addRow(label_Q1_answer, lineEdit_Q1_answer);
fields << lineEdit_Q1_answer;
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
form.addRow(&buttonBox);
QObject::connect(&buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()));
QObject::connect(&buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
bool click = true;
int code = dialog.exec();
bool passed = true;
while (click == true){
passed = true;
if (code == QDialog::Accepted) {
// check if empty questions were entered
if (lineEdit_Q1->text() == "" || lineEdit_Q2->text() == "" || lineEdit_Q3->text() == "") {
QMessageBox msgBox;
msgBox.setText("An error occured while entering questions for the P835 test");
msgBox.setInformativeText("You can not enter empty questions! Please try again or click cancel to use the standard questions!");
msgBox.setIcon(QMessageBox::Warning);
msgBox.exec();
passed = false;
dialog.close();
dialog.exec();
break;
}
if (lineEdit_Q1_answer->text().split(",").size() != 5 || lineEdit_Q2_answer->text().split(",").size() != 5 || lineEdit_Q3_answer->text().split(",").size() != 5) {
QMessageBox msgBox;
msgBox.setText("An error occured while entering question ratings for the P835 test");
msgBox.setInformativeText("You have to enter exactly 5 ratings for each question! Please try again or click cancel to use the standard ratings!");
msgBox.setIcon(QMessageBox::Warning);
msgBox.exec();
passed = false;
dialog.close();
dialog.exec();
break;
}
if (oneFileCheckBox->isChecked() && multipleFilesCheckBox->isChecked()) {
QMessageBox msgBox;
msgBox.setText("An error occured while setting up the P835 test...");
msgBox.setInformativeText("You cannot check both boxes! Please select only one option for the files!");
msgBox.setIcon(QMessageBox::Warning);
msgBox.exec();
passed = false;
dialog.close();
dialog.exec();
break;
}
if (oneFileCheckBox->isChecked() == false && multipleFilesCheckBox->isChecked() == false) {
QMessageBox msgBox;
msgBox.setText("An error occured while setting up the P835 test...");
msgBox.setInformativeText("You have to select one file option!");
msgBox.setIcon(QMessageBox::Warning);
msgBox.exec();
passed = false;
dialog.close();
dialog.exec();
break;
}
if (passed == true) {
this->configMgr->setQuestions(lineEdit_Q1->text(), lineEdit_Q2->text(), lineEdit_Q3->text());
this->configMgr->setAnswers(lineEdit_Q1_answer->text(), lineEdit_Q2_answer->text(), lineEdit_Q3_answer->text());
if(oneFileCheckBox->isChecked() == true) {
this->configMgr->fileOption = 0;
}
if(multipleFilesCheckBox->isChecked() == true) {
this->configMgr->fileOption = 1;
}
QMessageBox msgBox;
msgBox.setText("Success!");
msgBox.setInformativeText("The questions and the question ratings have been set successfully!");
msgBox.setIcon(QMessageBox::Information);
msgBox.exec();
dialog.close();
click = false;
}
if (code == QDialog::Rejected) {
this->configMgr->setQuestions(Q1_std, Q2_std, Q3_std);
this->configMgr->setAnswers(Q1_std_answer, Q2_std_answer, Q3_std_answer);
QMessageBox msgBox;
msgBox.setText("Setting standard values...");
msgBox.setInformativeText("Standard questions and ratings will be set. Click on the P835 button again to set questions and ratings manually!");
msgBox.setIcon(QMessageBox::Information);
msgBox.exec();
dialog.close();
click = false;
}
}
if (code == QDialog::Rejected) {
this->configMgr->setQuestions(Q1_std, Q2_std, Q3_std);
this->configMgr->setAnswers(Q1_std_answer, Q2_std_answer, Q3_std_answer);
QMessageBox msgBox;
msgBox.setText("Setting standard values...");
msgBox.setInformativeText("Standard questions and ratings will be set. Click on the P835 button again to set questions and ratings manually!");
msgBox.setIcon(QMessageBox::Information);
msgBox.exec();
dialog.close();
click = false;
}
}
In this example code I only put one text box where the user has to enter some information. I have six text boxes and two checkboxes.
I hope you can help me! Thank you!
You should use validation with QDialog::done(int r) or a QWizard. Qt makes this task relatively easy if you take the time to study the examples and documentation on it, but it does take time to learn it the first time.
Validation with QDialog::done(int r)
http://www.qtcentre.org/threads/8048-Validate-Data-in-QDialog
void DataSourceDlg::done(int r)
{
if(QDialog::Accepted == r) // ok was pressed
{
if(nodeLineEdit->text().size() > 3) // validate the data somehow
{
QDialog::done(r);
return;
}
else
{
statusBar->setText("Invalid data in text edit...try again...");
return;
}
}
else // cancel, close or exc was pressed
{
QDialog::done(r);
return;
}
}
Note that by subclassing QDialog and managing the done method you can prevent the dialog from closing and display a message.
QWizard and QWizardPage
http://doc.qt.io/qt-5/qwizard.html#details
Using a QWizard is a little more work, but it is built around validation and ensuring the correct information is in the right boxes.
Basically you subclass QWizard and QWizard page, and then you implement validatePage() and some others methods and you follow the examples and it works flawlessly. This used to be included in Qt Solutions and it was opened up a few years ago.
http://doc.qt.io/qt-5/qtwidgets-dialogs-classwizard-example.html
http://doc.qt.io/qt-5/qtwidgets-dialogs-licensewizard-example.html
companyLabel = new QLabel(tr("&Company name:"));
companyLineEdit = new QLineEdit;
companyLabel->setBuddy(companyLineEdit);
emailLabel = new QLabel(tr("&Email address:"));
emailLineEdit = new QLineEdit;
emailLineEdit->setValidator(new QRegExpValidator(QRegExp(".*#.*"), this));
emailLabel->setBuddy(emailLineEdit);
postalLabel = new QLabel(tr("&Postal address:"));
postalLineEdit = new QLineEdit;
postalLabel->setBuddy(postalLineEdit);
registerField("details.company*", companyLineEdit);
registerField("details.email*", emailLineEdit);
registerField("details.postal*", postalLineEdit);
* makes a field mandatory. QRegExpValidator makes sure the email address has an # sign in the middle.
QValidator with QLineEdit
http://doc.qt.io/qt-5/qvalidator.html#details
http://doc.qt.io/qt-5/qtwidgets-widgets-lineedits-example.html
validatorLineEdit->setValidator(new QIntValidator(
validatorLineEdit));
validatorLineEdit->setValidator(new QDoubleValidator(-999.0,
999.0, 2, validatorLineEdit));
QLineEdit::setInputMask(QString)
http://doc.qt.io/qt-5/qlineedit.html#inputMask-prop
inputMaskLineEdit->setInputMask("");
inputMaskLineEdit->setInputMask("+99 99 99 99 99;_");
inputMaskLineEdit->setInputMask("0000-00-00");
inputMaskLineEdit->setText("00000000");
inputMaskLineEdit->setCursorPosition(0);
inputMaskLineEdit->setInputMask(">AAAAA-AAAAA-AAAAA-AAAAA-AAAAA;#");
Regular Expressions
RegEx is awesome. Learning it is extremely useful (IMHO). I really like the tools and cheatsheets provided by gskinner. http://regexr.com/
http://doc.qt.io/qt-5/qregexpvalidator.html#details
// regexp: optional '-' followed by between 1 and 3 digits
QRegExp rx("-?\\d{1,3}");
QValidator *validator = new QRegExpValidator(rx, this);
QLineEdit *edit = new QLineEdit(this);
edit->setValidator(validator);
Hope that helps.

How to delete selected row from TableView? (JavaFX with FXML)

So, I'm trying to delete the highlighted row in TableView in my program.
I've looked at loads of tutorials online, but really can't get my head around this.
I have followed the example from CodeMakery, which is in Eclipse, but I'm unable to get it to work on IntelliJ (because of some apparent JDK problems?)
This is the code from CodeMakery:
private void handleDeletePerson() {
int selectedIndex = personTable.getSelectionModel().getSelectedIndex();
if (selectedIndex >= 0) {
personTable.getItems().remove(selectedIndex);
} else {
// Nothing selected.
Alert alert = new Alert(AlertType.WARNING);
alert.initOwner(mainApp.getPrimaryStage());
alert.setTitle("No Selection");
alert.setHeaderText("No Person Selected");
alert.setContentText("Please select a person in the table.");
alert.showAndWait();
}
}
Could you please help me understand how to make selected row get deleted?
just add at the beginning of this method personTable.setEditable(true). Should work now.

DevExress XtraGrid MouseDown Event does not fire second time

I have the MouseDown Event on my XtraGrid, that doesn't want to fire the second time on the same column.
It recognizes the first click, but unless I click another column or row before attempting to click the original row/column, nothing happens.
Can anyone tell me what I am missing? Here is the code in the MouseDown event:
var hitInfo = gridViewSpecialty.CalcHitInfo(e.Location);
if (hitInfo.InRowCell)
{
int nRow = hitInfo.RowHandle;
GridColumn column = hitInfo.Column;
LinkClick(nRow, column);
}
Thanks!! Bob
It's most likely due to the event erroring out. I'd be willing to bet if you put a Try{}catch{} around that statement, you may trap the error.
Here's what I use when trying to capture a user click event with a grid. I use the double-click event, like so:
private void gcMainGrid_DoubleClick(object sender, EventArgs e)
{
try
{
GridControl gc = (GridControl)sender;
DevExpress.Utils.DXMouseEventArgs dxMEA = (DevExpress.Utils.DXMouseEventArgs)e;
GridView gv = (GridView)gc.MainView;
int iRowHandle = gv.CalcHitInfo(dxMEA.X, dxMEA.Y).RowHandle;
//Check to see if the user is on a row.
if (iRowHandle >= 0)
{
//Do something here.
}
catch(Exception ex)
{
if (Debugger.IsAttached)
Debugger.Break();
else
throw(ex);
}
}
That will get me the RowHandle of the row that the user clicks on. I think that's what you're after but I wouldn't use the mouse-down event for that.

Trouble getting `QWidget* editor` for a `QModelIndex`

I am having trouble augmenting the default edit behavior of QTableView. I want the following behavior when the Enter key is pressed:
Start editing the current cell if it is not already being edited.
If the cell is being edited,
2a. commit the data and close the editor. Then,
2b. make the cell below, if present, the current cell.
2a is the default behavior, and 2b can likely be achieved by using QAbstractItemView::setCurrentIndex() in a re-implementation of QItemDelegate::eventFilter() (as suggested here in a similar context).
The problem is in achieving 1. I list below the approaches I have tried till now.
Reconfigure the "platform edit key" By default, "Editing starts when the platform edit key has been pressed over an item." (QAbstractItemView::EditKeyPressed) This key is F2 on my platform (Ubuntu 12.04). I could reconfigure the platform edit key to Enter but
Altering platform defaults seems like a bad idea.
I could not find out how to do it.
Capture the Enter key press I use QShortCut to do this as follows:
class CourseTable : public QTableView {
/* ... */
};
/* ... */
CourseTable::CourseTable(/* ... */) {
/* ... */
QShortcut* shortcut = new QShortcut(QKeySequence(Qt::Key_Return), this);
connect(shortcut, SIGNAL(activated()), this, SLOT(handleEnter_()));
/* ... */
}
/* ... */
void CourseTable::handleEnter_() {
QModelIndex idx = this->currentIndex();
if (this->state() != QAbstractItemView::EditingState)
this->edit(idx);
/* else // see below */
}
This does capture the Enter key-press and accomplishes 1 (from above) but now 2 is broken. So, I need to look into the else clause in CourseTable::handleEnter_() above, possibly calling QAbstractItemView::commitData() and QAbstractItemView::closeEditor in it. The problem is that both these functions require a QWidget *editor argument which I just cannot figure out how to get. I could subclass QAbstractItemDelegate, add a getEditor() method to the derived class, and modify existing code to pass instances of the derived delegate class to CourseTable::setItemDelegate*() functions. But that sounds like too much work.
So, any ideas how I can cleanly accomplish both 1 and 2 without having to rewrite my code?
Why cant you just filter the event also for starting the edit?
Just handle the event if state is != QAbstractItemView::EditingState
Returning true in this function makes the event stop propagating to the filtered object.
If state is Editing you can just return falseand allow the table and editor continue processing the event.
Something like this:
bool FilterObject::eventFilter(QObject *object, QEvent *event)
{
if (object == tableView && event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Return && tableView->state() != QAbstractItemView::EditingState) {
// set current cell to edit
return true;
} else
return false;
}
return false;
}

Resources