如何在QTableView中检测doubleClick

时间:2010-12-01 11:47:35

标签: qt qt4 pyqt

我使用PyQt创建GUI应用程序。在从QTableView继承的视图中,需要检测用户双击行时选择的行。该表有排序,但没有编辑。

我该怎么办?

注意 - 尝试了doubleClicked(int)信号。它是由鼠标按钮发出的,而不是由数据单元发出的,所以它从未被触发过。 :(

伊恩

4 个答案:

答案 0 :(得分:16)

我不明白。 QTableView的doubleClicked信号具有签名

void doubleClicked ( const QModelIndex & index )

如果连接该信号,则应获得正确的QModelIndex。

答案 1 :(得分:5)

不再需要使用SIGNAL:

self.your_table.doubleClicked.connect(your_function)

“doubleClicked”继承自QAbstractItemView。

答案 2 :(得分:3)

一旦你有了modelIndex(来自上面的Frank评论),你就可以用它来找到双击了哪个单元格。

def slotDoubleClicked(self, mi):
    row = mi.row()
    column = mi.column()

然后,您可以使用这些行和列值来使用table.setItem(row,column,newdata)或其他表方法访问该表

答案 3 :(得分:1)

就像@regomodo所说,您可以通过以下方式将函数简单地连接到双击上:

public partial class Form1 : Form
{
    // Program Settings and Controls
    private readonly Panel pnlBacteria;             // Panel representing a piece of bacteria
    private readonly Random random = new Random();  // For randomly-generated values
    private readonly Timer tmrMoveBacteria;         // Timer used for bacteria movement
    private readonly int bacteriaSize = 20;         // Stores the size for our bacteria
    private const int maxDistance = 50;             // The maximum number of moves allowed in the same direction.
    private const int stepDistance = 3;             // The distance to travel on each iteration of the timer. Smaller number is slower and smoother
    private readonly List<int> weightedDistances;   // Contains a weighted list of distances (lower numbers appear more often than higher ones)

    // Bacteria state variables
    private Direction direction;  // Stores the current direction bacteria is moving
    private int distance;         // Stores the distance remaining to travel in current direction

    // Represents possible directions for bacteria to move
    private enum Direction
    {
        North, NorthEast, East, SouthEast, South, SouthWest, West, NorthWest
    }

    public Form1()
    {
        InitializeComponent();

        // Initialize our weighted differences array so that 1 is  
        // chosen most often and maxDistance is chosen the least often
        weightedDistances = new List<int>();
        for (var i = 0; i < maxDistance; i++)
        {
            var weight = maxDistance / (i + 1);

            for (var j = 0; j <= weight; j++)
            {
                weightedDistances.Add(i + 1);
            }
        }

        // Give life to the bacteria
        pnlBacteria = new Panel
        {
            BackColor = Color.Red,
            Width = bacteriaSize,
            Height = bacteriaSize,
            Left = random.Next(0, ClientRectangle.Width - bacteriaSize),
            Top = random.Next(0, ClientRectangle.Height - bacteriaSize)
        };
        Controls.Add(pnlBacteria);

        // Start bacteria movement timer
        tmrMoveBacteria = new Timer {Interval = 10};
        tmrMoveBacteria.Tick += TmrMoveBacteria_Tick;
        tmrMoveBacteria.Start();
    }

    /// <summary>
    /// Sets the direction and distance fields to valid values based on the
    /// current bacteria position, direction, and remaining distance
    /// </summary>
    private void UpdateDirectionAndDistance()
    {
        // Get all directions
        var validDirections = Enum.GetValues(typeof(Direction)).Cast<Direction>();

        // Remove invalid directions (based on the bacteria position)
        if (pnlBacteria.Top < bacteriaSize) validDirections = 
            validDirections.Where(dir => !dir.ToString().Contains("North"));

        if (pnlBacteria.Right > ClientRectangle.Width - bacteriaSize) validDirections = 
            validDirections.Where(dir => !dir.ToString().Contains("East"));

        if (pnlBacteria.Left < bacteriaSize) validDirections = 
            validDirections.Where(dir => !dir.ToString().Contains("West"));

        if (pnlBacteria.Bottom > ClientRectangle.Height - bacteriaSize) validDirections = 
            validDirections.Where(dir => !dir.ToString().Contains("South"));

        // If we're supposed to keep on moving in the same 
        // direction and it's valid, then we can exit
        if (distance > 0 && validDirections.Contains(direction)) return;

        // If we got here, then we're setting a new direction and distance
        distance = weightedDistances[random.Next(weightedDistances.Count)];
        var directions = validDirections.Where(d => d != direction).ToList();
        direction = directions[random.Next(directions.Count)];
    }

    /// <summary>
    /// Executes on each iteration of the timer, and moves the bacteria
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void TmrMoveBacteria_Tick(object sender, EventArgs e)
    {
        // Ensure direction and distance are valid
        UpdateDirectionAndDistance();

        // Move the bacteria
        var dirStr = direction.ToString();
        if (dirStr.Contains("North")) pnlBacteria.Top -= stepDistance;
        if (dirStr.Contains("East")) pnlBacteria.Left += stepDistance;
        if (dirStr.Contains("South")) pnlBacteria.Top += stepDistance;
        if (dirStr.Contains("West")) pnlBacteria.Left -= stepDistance;

        distance--;
    }
}

然后,如果您想知道用户双击了哪一行,可以使用以下代码:

self.your_table.doubleClicked.connect(your_function)

它将返回对应于行号或列号的整数。 双击将删除先前的选择,因此始终只有一个值。

如果将功能链接到按钮或其他信号,则会收到包含用户选择的多个元素的列表。

例如,您可以使用以下代码轻松检索所有选定行的列表:

for idx in self.your_table.selectionModel().selectedIndexes():
        row_number = idx.row()
        column_number = idx.column()

这将返回所有选定行的列表(set函数还将删除所有重复项)。

干杯!