【问题标题】:Get index of QPushButton on 2D array QPushButton获取二维数组 QPushButton 上 QPushButton 的索引
【发布时间】:2014-03-25 16:52:49
【问题描述】:

我有一个二维数组QPushButton,当用户点击它时如何获取按钮的索引?比如当用户点击按钮a[2][3]时会显示(2,3)?

【问题讨论】:

  • 您需要稍微扩展一下,您是如何创建按钮的?你是如何添加它们的?你想在哪里展示这个价值?

标签: c++ qt


【解决方案1】:

示例如下所示:

Qt 4/5 使用对象名称

您可以为按钮指定唯一的对象名称。理想情况下,名称应该是有效的 C++ 标识符。

// https://github.com/KubaO/stackoverflown/tree/master/questions/button-grid-22641306
#include <QtGui>
#if QT_VERSION_MAJOR >= 5
#include <QtWidgets>
#endif

struct Display : QLabel {
   Q_SLOT void onClicked() {
      auto const elements = sender()->objectName().split('_');
      auto const i = elements.at(1).toInt();
      auto const j = elements.at(2).toInt();
      setText(QString{"(%1,%2)"}.arg(i).arg(j));
   }
   Q_OBJECT
};

int main(int argc, char *argv[])
{
   QApplication a{argc, argv};
   QWidget window;
   QGridLayout layout{&window};
   QVarLengthArray<QPushButton, 12> buttons(12);
   Display display;

   const int rows = 4, columns = 3;
   for (int i = 0; i < rows; ++ i)
      for (int j = 0; j < columns; ++j) {
         auto & button = buttons[i*columns+j];
         button.setText(QString{"(%1,%2)"}.arg(i).arg(j));
         button.setObjectName(QString{"buton_%1_%2"}.arg(i).arg(j));
         layout.addWidget(&button, i, j);
         display.connect(&button, SIGNAL(clicked()), SLOT(onClicked()));
      }
   layout.addWidget(&display, rows, 0, 1, columns);

   window.show();
   return a.exec();
}
#include "main.moc"

Qt 5 - 使用 Lambdas

在 Qt 5 和 C++11 中,您应该使用函子即时为每个按钮生成自定义插槽。例如:

// https://github.com/KubaO/stackoverflown/tree/master/questions/button-grid-22641306
#include <QtWidgets>

int main(int argc, char *argv[])
{
   QApplication a{argc, argv};
   QWidget window;
   QGridLayout layout{&window};
   QVarLengthArray<QPushButton, 12> buttons(12);
   QLabel display;

   const int rows = 4, columns = 3;
   for (int i = 0; i < rows; ++ i)
      for (int j = 0; j < columns; ++j) {
         auto text = QStringLiteral("(%1,%2)").arg(i).arg(j);
         auto & button = buttons[i*columns+j];
         button.setText(text);
         layout.addWidget(&button, i, j);
         QObject::connect(&button, &QPushButton::clicked, [&display, text] {
            display.setText(text);
         });
      }
   layout.addWidget(&display, rows, 0, 1, columns);

   window.show();
   return a.exec();
}

Qt 4/5 - 使用 QSignalMapper

QSignalMapper 非常适合您的需求。它使您可以将QObject* 映射到“其他内容”,例如字符串。例如:

#include <QtGui>
#if QT_VERSION_MAJOR >= 5
#include <QtWidgets>
#endif

int main(int argc, char *argv[])
{
   QApplication a{argc, argv};
   QSignalMapper mapper;
   QWidget window;
   QGridLayout layout{&window};
   QVarLengthArray<QPushButton, 12> buttons(12);
   QLabel display;

   const int rows = 4, columns = 3;
   for (int i = 0; i < rows; ++ i)
      for (int j = 0; j < columns; ++j) {
         auto text = QString{"(%1,%2)"}.arg(i).arg(j);
         auto & button = buttons[i*columns+j];
         button.setText(text);
         layout.addWidget(&button, i, j);
         mapper.connect(&button, SIGNAL(clicked()), SLOT(map()));
         mapper.setMapping(&button, text);
      }
   display.connect(&mapper, SIGNAL(mapped(QString)), SLOT(setText(QString)));
   layout.addWidget(&display, rows, 0, 1, columns);

   window.show();
   return a.exec();
}

Qt 4/5 - 使用属性系统

您可以利用QWidgetQObject 的事实。 QObjects 有一个属性系统,因此您可以将每个按钮的索引设置为一个属性,然后在连接到clicked() 信号的槽中检索它。例如:

#include <QtGui>
#if QT_VERSION_MAJOR >= 5
#include <QtWidgets>
#endif

const char kIndex[] = "index";
struct Display : QLabel {
   Q_SLOT void onClicked() {
      setText(sender()->property(kIndex).toString());
   }
   Q_OBJECT
};

int main(int argc, char *argv[])
{
   QApplication a{argc, argv};
   QWidget window;
   QGridLayout layout{&window};
   QVarLengthArray<QPushButton, 12> buttons(12);
   Display display;

   const int rows = 4, columns = 3;
   for (int i = 0; i < rows; ++ i)
      for (int j = 0; j < columns; ++j) {
         auto index = QString{"(%1,%2)"}.arg(i).arg(j);
         auto & button = buttons[i*columns+j];
         button.setText(index);
         button.setProperty(kIndex, index);
         layout.addWidget(&button, i, j);
         display.connect(&button, SIGNAL(clicked()), SLOT(onClicked()));
      }
   layout.addWidget(&display, rows, 0, 1, columns);

   window.show();
   return a.exec();
}
#include "main.moc"

【讨论】:

  • 太棒了,我总是喜欢能够展示实现同一目标的多种方法的答案,并且“整体大于部分之和。”
【解决方案2】:

通常,您必须遍历数组并测试事件目标是否与每个元素相等,直到达到正确的索引

【讨论】:

  • 一般来说,不会。您可以使用属性系统,也可以使用 lambda。没有必要将指向按钮的指针保存在单独的数组中。
  • 见鬼,你也可以使用QSignalMapper
  • 我的意思是,一般来说,这就是幕后发生的事情,如果在某些情况下手动完成,可能会导致更快的代码,但您的信息很可能对发帖人有益
猜你喜欢
  • 2017-05-26
  • 2022-01-03
  • 2013-05-02
  • 2022-10-25
  • 1970-01-01
  • 2021-02-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多