Alright I tried using a QMaemo5ListPickSelector together with a QMaemo5ValueButton, but when I click on the button, a popup dialog box does come up, but it doesnt any list ..
Here is a picture of what I mean:
This is the code I'm using to start up the above mentioned two components and to populate the lists:
QMaemo5ValueButton *x = new QMaemo5ValueButton("Testing .. !");
QStandardItemModel model (10,2);
int j,k;
for(j=0;j<=1;j++)
{
k=0;
for(i=0;i<=9;i++)
{
QStandardItem *item = new QStandardItem(QString("%0").arg(k));
k+=5;
model.setItem(i,j,item);
}
}
x->setValueLayout(QMaemo5ValueButton::ValueBesideText);
QMaemo5ListPickSelector *sel = new QMaemo5ListPickSelector();
sel->setModel(&model);
x->setPickSelector(sel);
hbox->addWidget(x);
I would say I'm probably populating the list incorrectly ..
Related
I've searched many places and found lots of interesting information, but none of that seems to work for what I want. I've tried to follow the solution shown at https://stackoverflow.com/a/9986293/11035837 to no avail.
Basics of my structure: I have a QTreeWidget. I add top level QTreeWidgetItems dynamically (upon the push of a button in a header button box). Each top level QTreeWidgetItem then gets other widgets added to it using:
QTreeWidget* treeWidget = new QTreeWidget;
QTreeWidgetItem* new_record = new QTreeWidgetItem;
QPushButton* add_child = new QPushButton;
QLineEdit* user_input = new QLineEdit;
treeWidget->setItemWidget(new_record,1,add_child);
treeWidget->setItemWidget(new_record,2,user_input);
The add_child button works perfectly. I have a display that inserts all my QLabels, QLineEdits, and QPushButtons in a tree tiered fashion. My buttons work for adding and removing the visual display of items even triggering the visibility of various other elements.
However, I cannot get the user input data out of the QLineEdits to process for anything (such as writing to an output file).
I have my output function iterate through the QTreeWidget:
QTreeWidgetItemIterator iter(treeWidget);
while (*iter)
{
stream.writeStartElement("record");
if ((*iter) != nullptr)
{
for (int i = 0; i < 12; i++)
{
if((*iter)->text(i) != nullptr) stream.writeAttribute("record_name", (*iter)->text(i));
}
}
for (int i = 0; i < 12; i++)
{
if ((*iter) != nullptr && (*iter)->child(i) != nullptr)
{
for (int j = 0; j < 12; j++)
{
if ((*iter)->child(i)->text(j) != nullptr) stream.writeAttribute("record_name", (*iter)->child(i)->text(j));
}
}
}
++iter;
}
This prints as many records with record_name displayed as were created, but it doesn't display any of the other data, because the pointer defined by (*iter)->child(i) is nullptr regardless of i
I then tried using data();
stream.writeAttribute("record_name ", (*iter)->data(2, Qt::UserRole).toString());
This doesn't err out because of nullptr, but it prints out record_name="" rather than record_name="<user_input>"
I'm able to get the user input for QLineEdit widgets that are not in the QTreeWidget, just not the ones in the tree. I assume if I can figure out how to get the data out of the QLineEdits within the tree that I should be able to adapt that to getting the QLineEdits out of a custom QWidget also within the tree.
I found a solution using information from https://www.qtcentre.org/threads/23228-typecast-of-QWidget
stream.writeAttribute("record_name", qobject_cast<QLineEdit*>(treeWidget->itemWidget((*iter), 2))->text() );
The issue was that the QLineEdit widgets were being recalled as QWidgets and not as QLineEdit widgets and as such the text() method/function was not available to it until I cast it back as the desired type.
I have a QTableView that shows QSqlQueryModel. The model contains checkboxes that are created in each row in the first column (which contain the ref_no; the primary-key in my db) as follow:
void MainWindow::showM(model){
ui->tableView->setModel(model);
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
for( int i = 0; p<model->rowCount(); i++)
{
QCheckBox *checkBox = new QCheckBox();
ui->tableView->setIndexWidget(model->index(i,0),checkBox);
}
ui->tableView->show();
}
... and it's working fine, displaying all the information I need plus the checkboxes.
Now, I need to get the ref_no where the adjacent checkbox is checked.
How to do that ?
Use QSignalMapper (or an ad hoc solution involving a mapper using sender(), or lambdas). For instance define a member for the mapping:
QHash<QCheckBox *, int> m_mapping;
Then in your code hook it up like this:
QCheckBox *checkBox = new QCheckBox();
ui->tableView->setIndexWidget(model->index(i,0),checkBox);
m_mapping[checkBox] = i;
connect(checkBox, &QCheckBox::toggled, this, &MainWindow::onCheckBoxToggled);
Then define a slot like this:
// for the love of kittens use proper names for methods
void MyWindow::onCheckBoxToggled(bool toggled) {
QCheckBox *box = static_cast<QCheckBox *>(sender());
const int id = m_mapping.value(box);
// do something
}
Or, if you fancy lambdas, you can do the above with a capture:
connect(checkBox, &QCheckBox::toggled,
[i](bool toggled){ /* use i, toggled */ });
All of that having being said, I would strongly recommend against the idea of creating QCheckBoxes and using setIndexWidget. Instead, employ a proxy model that enriches your column by returning the Qt::ItemIsUserCheckable flag and handles reads and writes for the Qt::CheckStateRole.
I want to create an editable QComboBox which filters results according to the search query and updates the dropdown entries accordingly.
After reading How do I Filter the PyQt QCombobox Items based on the text input? I tried to implement something similar in C++.
But I can't store anything inside the QComboBox now. Even after adding new entries through addItem() the total count remains 0.
What is the reason for this and how do I insert entries inside the QComboBox with QSortFilterProxyModel?
Here is the relevant snippet of the code:
SearchBox = new QComboBox(this);
SearchBox->setEditable(true);
// Try adding a few entries and check if they persist after changing the model
SearchBox->addItem(QString("hi"));
SearchBox->addItem(QString("bye"));
int count = SearchBox->count(); // count = 2
ProxyModel = new QSortFilterProxyModel;
ProxyModel->setSourceModel(SearchBox->model());
ProxyModel->setFilterCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
SearchBox->setModel(ProxyModel);
// Check count again
count = SearchBox->count(); // count = 0 <- Why?
// Try adding new entries
SearchBox->addItem(QString("Hi again"));
count = SearchBox->count(); // count = 0 .. So new entries don't get stored
Completer = new QCompleter(ProxyModel,this);
Completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
SearchBox->setCompleter(Completer);
QObject::connect(SearchBox->lineEdit(), SIGNAL(textChanged(const QString)), ProxyModel, SLOT(setFilterFixedString(const QString)));
QObject::connect(Completer, SIGNAL(activated(const QString &)), this, SLOT(onCompleterActivated(const QString &)));
Use QStringListModel to store items. Application crashes if proxy model have no items (if filter string filters out all items)(this needs further investigation - is this completer issue or combobox). This can be fixed by not applying such filter (onTextChanged(QString text) slot). Completer completes input if theres only one item (not sure if it's ok). And sometimes checkbox doubles all items (don't know why). If this issues is critical, I think you need to write custom ComboBox from scratch and this is serious work.
{
SearchBox = new QComboBox(this);
SearchBox->setEditable(true);
QStringList Items;
Items << "hi" << "bye";
StringListModel = new QStringListModel();
StringListModel->setStringList(Items);
ProxyModel = new QSortFilterProxyModel;
ProxyModel->setSourceModel(StringListModel);
ProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
SearchBox->setModel(ProxyModel);
// Check count again
int count = SearchBox->count(); // count = 2
// Try adding new entries
QStringList Items_ = StringListModel->stringList();
Items_ << "hi again";
StringListModel->setStringList(Items_);
count = SearchBox->count(); // count = 3
Completer = new QCompleter(ProxyModel,this);
Completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
SearchBox->setCompleter(Completer);
QObject::connect(SearchBox->lineEdit(), SIGNAL(textChanged(const QString)), this, SLOT(onTextChanged(QString)));
QObject::connect(Completer, SIGNAL(activated(const QString &)), this, SLOT(onCompleterActivated(const QString &)));
}
void MainWindow::onTextChanged(QString Text) {
QStringList Items = StringListModel->stringList();
QString Item;
foreach(Item,Items) {
if (Item.indexOf(Text) > -1) {
ProxyModel->setFilterFixedString(Text);
return;
}
}
}
I have a QListview where I have set a model. The model contains the QList. Now I want to get the contents of QListview on clicking the item. But I don't know how to do this? Through some tutorials I followed I am able to get two items appear in the QListview as follows. But I dont know how to make it work?? Please anyone help. The code which I am working as follows.
listviewmodel =new QListView;
listviewmodel->setModel( createModel() );
listviewmodel->setViewMode(QListView::IconMode);
listviewmodel->setIconSize(QSize(size().width()/8, size().height()/8));
connect(listviewmodel,SIGNAL(clicked(const QModelIndex)),this,SLOT(ItemClicked(QModelIndex)));
QAbstractItemModel *MainWindow::createModel()
{
QStandardItemModel *model = new QStandardItemModel();
QList<QStandardItem *> listItem;
QStandardItem *item2 = new QStandardItem();
item2->setIcon(QIcon(QPixmap::fromImage(qimages2)));
listItem << item2;
QStandardItem *item1 = new QStandardItem();
item1->setIcon(QIcon(QPixmap::fromImage(qimages1)));
listItem << item1;
model->appendColumn(listItem);
return model;
}
void MainWindow::ItemClicked (QModelIndex index )
{
textEdit->setText(index.data().toString());
}
I checked your code in QtCreator and it works as you described. So what is the problem? Are you getting some errors? Maybe did you not put declaration of ItemClicked(QModelIndex) below the public slots:? Are you sure that connect returns true? Try to check it:
bool success = connect(listviewmodel,SIGNAL(clicked(const QModelIndex)),this,SLOT(ItemClicked(QModelIndex)));
Q_ASSERT(success);
EDIT: If you want to display only icons at QListView and get some text informations after clicking on specified item, you can do it in the following way:
item2->setIcon(QIcon(QPixmap::fromImage(qimages2)));
item2->setData("informations about item2", Qt::UserRole);
(...)
void MainWindow::ItemClicked (QModelIndex index )
{
QString data = index.data(Qt::UserRole).value<QString>();
ui->textEdit->setText(data);
}
I generate checkboxes as follows:
foreach(QString filt, types){
QCheckBox *checkbox = new QCheckBox(filt, this);
checkbox->setChecked(true);
vbox->addWidget(checkbox);
}
I need to get access to these checkboxes by name but they are all called the same?
I need to read the text they display.
How can I go about this?
Is it possible to run a for loop and attach the value of i onto the end of the checkbox. So in effect, the checkbox would be called checkbox[0], checkbox [1], etc?
EDIT:
I've changed the code to the following:
for(int i=0; i<types.count(); ++i)
{
QString filt = types[i];
*checkboxCount = *checkboxCount + 1;
QCheckBox *typecheckbox[i] = new QCheckBox(filt, this);
typecheckbox[i]->setChecked(true);
vbox->addWidget(typecheckbox[i]);
}
I thought this was a way to dynamically name the checkboxes so I can loop through them to get the text value from them.
I'm getting the error 'variable-sized object may not be initialized' on this line QCheckBox *typecheckbox[i] = new QCheckBox(filt, this);
Any ideas to a solution/ alternate approach?
If you want to access the checkboxes later, you can just use the find children method as follows:
QStringList myStringList;
QList<QCheckBox *> list = vbox->findChildren<QCheckBox *>();
foreach (QCheckBox *checkBox, list) {
if (checkBox->isChecked())
myStringList.append(checkBox->text());
}