2016-02-01 3 views
1

Я довольно новичок в c++ and qt. Я не уверен, пользуюсь ли я правильной терминологией описанием того, чего я хочу достичь. Но здесь все идет.Qt сигналы и слоты, передающие данные

Мое приложение spawns and removes widgets in a gridlayout, когда пользователь pushes buttons. Удалось сделать это успешно. Однако, когда пользователь использует порожденные виджеты, мне нужен widgets to interact with each other.

QList<QLineEdit*> m_ptrLEPathList; 
QList<QPushButton*> m_ptrPBList; 

qint8 m_noFields; 

void MainWindow::on_pbIncFields_clicked() 
{ 
    //create widgets and place on a new row in a gridLayout 
    QLineEdit *lineEditPath = new QLineEdit(this); 
    QPushButton *pushButton = new QPushButton(this); 

    //storing pointers in lists to be able to delete them later. 
    m_ptrLEPathList.append(lineEditPath); 
    m_ptrPBList.append(pushButton); 

    ui->gridLayout->addWidget(m_ptrLEPathList.last(),m_noFields,0); 
    ui->gridLayout->addWidget(m_ptrPBList.last(),m_noFields,1); 

    connect(m_ptrPBList.last(), SIGNAL(clicked(bool), this, SLOT(on_addPath())); 
    m_noFields++; 
} 

void MainWindow::on_pbDecFields() 
{ 
    //delete last spawned widgets 
} 

void MainWindow::on_addPath() 
{ 
    QFileDialog getPath(); 
    getPath.exec(); 

    //somehow set the text of the line edit spawned on the same row as the pushbutton 

} 

Так что мой слот выполняется, когда я нажимаю любую кнопку порождены, но я не знаю, как store the data from the file dialog in the related lineEdit.

Является основной идеей того, что я пытаюсь сделать нормально, или есть ли какое-либо другое решение для достижения fuctionality, которое я ищу?

ответ

2

В on_addPath слот можно использовать QObject::sender метод, чтобы получить нажал кнопку, и, предполагая m_ptrLEPathList и m_ptrPBList списка равны, вы можете легко получить соответствующие QLineEdit:

void MainWindow::on_addPath() 
{ 
    QFileDialog dialog; 
    if (!dialog.exec()) 
    { 
     return; 
    } 

    QStringList fileNames = dialog.selectedFiles(); 
    if (fileNames.isEmpty()) 
    { 
     return; 
    } 

    QPushButton *btn = qobject_cast<QPushButton*>(sender()); 
    if (!btn) 
    { 
     return; 
    } 

    Q_ASSERT(m_ptrPBList.size() == m_ptrLEPathList.size()); 

    int index = m_ptrPBList.indexOf(btn); 
    if (index == -1) 
    { 
     return; 
    } 

    QLineEdit *edit = m_ptrLEPathList.at(index); 
    edit->setText(fileNames.first()); 
} 
+0

Да список должен оставаться одинакового размера. Пробовал ваше решение, и он работал красиво! Спасибо. – flog

0

Добавить карту в приватной секции

QMap<QPushButton*, QLineEdit*> map; 

Тогда

QLineEdit *lineEditPath = new QLineEdit(this); 
QPushButton *pushButton = new QPushButton(this); 
map.insert(pushButton, lineEditPath); 

Вы можете использовать отправителя() метод, как следующие:

void on_addPath() 
    { 
     QFileDialog getPath(); 
     getPath.exec(); 

     QObject* obj = sender(); 
     QPushButton *pb = 0; 
     if((pb = qobject_cast<QPushButton *>(obj)) != 0) { 
      QLineEdit* lineEdit = map->value(pb, 0); 
      if(lineEdit != 0) 
       lineEdit->setText(getPath.<some function to get selected file name>); 
     }   

    } 
+0

'sender()' метод вернет 'QPushButton', который был нажат. Кроме того, код не будет компилироваться, потому что вы пытаетесь назначить два указателя несовместимых типов: 'QToolButton *' to 'QLineEdit *'. – hank

+0

Моя ошибка. Извините ребята!...Один момент –

0

Вы в том числе функции «on_addPath» из сферы действия класса «MainWindow», поэтому, когда вызывается слот вы не доступ к члену элементов в классе.

Попробуйте включить функцию слота в класс и проверьте, есть ли у вас прямой доступ к элементам-членам. Кроме того, элемент 'lineEditPath' должен быть объектом-членом, поэтому он должен быть включен в определение класса.

Что-то вроде этого:

void MainWindow::on_addPath() 
{ 
    QFileDialog getPath(); 
    getPath.exec(); 

    QStringList fileNames = dialog.selectedFiles(); 
    if (fileNames.isEmpty()) 
    { 
     return; 
    } 

    m_lineEditPath->setText(fileNames.first()); 
} 
+0

oh вне сферы fuction был просто ошибкой, когда я написал вопрос. Сообщение отредактировано. – flog

0

Во-первых, void on_addPath() должен быть void MainWindow::on_addPath()

Как для связывания данных с QFileDialog просто. Попробуйте это:

void MainWindow::on_addPath() { 
    /* Get the push button you clicked */ 
    QPushButon *btn = qobject_cast<QPushButton*>(sender()); 

    /* Make sure both the lists have the same size */ 
    Q_ASSERT(m_ptrPBList.size() == m_ptrLEPathList.size()); 

    /* If the sender is a button in your list */ 
    if (m_ptrPBList.contains(btn)) { 
     /* Get the index of your push button */ 
     int idx = m_ptrPBList.indexOf(btn); 

     /* Get the corresponding line edit */ 
     QLineEdit *le = m_ptrLEPathList.at(idx); 

     /* Get your path */ 
     QString path = QFileDialog::getOpenFileName(this, "Caption", "Default Location"); 

     /* If you path is not empty, store it */ 
     if (not path.isEmpty()) 
      le->setText(path); 
    } 
} 
0

Я думаю, что чистое решение будет содержать QLineEdit и QPushButton в классе пользовательского виджета, если он подходит для вашего проекта. Таким образом, вы можете использовать диалог файла внутри этого класса, и вам не нужно будет хранить виджеты в списках. Трудно дать вам всю информацию, так как вы не представили никаких подробностей о том, что должно делать ваше приложение. Но в любом случае, пользовательский класс виджет будет выглядеть следующим образом (вы должны определить все функции внутри .cpp файла):

#ifndef WIDGETCONTAINER_H 
#define WIDGETCONTAINER_H 

#include <QWidget> 
#include <QLayout> 
#include <QLineEdit> 
#include <QPushButton> 
#include <QFileDialog> 

class WidgetContainer : public QWidget 
{ 
    Q_OBJECT 
    public: 
    WidgetContainer(QWidget *parent = 0) : QWidget(parent) 
    { 
     setLayout(new QHBoxLayout); 
     button.setText("BUTTON"); 
     layout()->addWidget(&lineEdit); 
     layout()->addWidget(&button); 

     connect(&button, SIGNAL(clicked()), this, SLOT(buttonPressed())); 
    } 

private: 
    QLineEdit lineEdit; 
    QPushButton button; 

private slots: 
    void buttonPressed() 
    { 
     QString filename = QFileDialog::getSaveFileName(); 
     lineEdit.setText(filename); 
    }  

}; 

#endif // WIDGETCONTAINER_H 
+0

Я вижу, где вы собираетесь с этим решением. Это, вероятно, соответствовало бы моим потребностям. Мое приложение читает обновленные дейтаграммы с разделенными запятыми строками в них. Пользовательские спам-виджеты предназначены для того, чтобы пользователь мог называть каждое поле во входящей строке и добавлять в строку больше полей. Когда строка придет, настройки, предоставленные пользователем, будут использоваться для форматирования окончательного отображения данных. Таким образом, в каждой строке есть больше виджетов, чем описано в моей проблеме. – flog

+0

Возможно, вы должны создать собственный виджет, который представляет каждую строку. Вы даже можете разделить строки на более мелкие куски, если хотите, или вам нужно. Если целью редактирования строки и кнопки является предоставление текста вместо файла, вы должны подумать об использовании ['QInputDialog :: getText'] (http://doc.qt.io/qt-5/qinputdialog.html #getText). Это статическая функция, поэтому ее можно использовать так же, как я использовал 'QFileDialog :: getSaveFileName();'. – thuga

+0

Одна из редакций строк будет использоваться для отображения каталога, указанного пользователем в filedialog. указанная папка позже будет отсканирована, чтобы проверить файл с последней модификацией. Я собираюсь попробовать ваше решение. Похоже, он немного починит мой код. – flog

Смежные вопросы