S
S
Sergey Tryapkin2015-06-29 16:08:41
Python
Sergey Tryapkin, 2015-06-29 16:08:41

How to add a unique attribute to a PyQT button?

Good afternoon!
After quite a long time trying to write my own parser for news sites, I had the idea to wrap it all in a shell, and then problems immediately appeared. The crux of the matter is this, there is this code:

class Reader(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):
        #кнопки
        grid = QGridLayout()
        self.setLayout(grid)

        positions = [(i,j) for i in range(15) for j in range(1)]

        for position, name, ahref in zip(positions, names, a_href):
            button = QPushButton(name, self)
            open_url = ahref
            print(open_url)
            button.setToolTip(ahref)
            button.clicked.connect(lambda: self.initNew(open_url))
            grid.addWidget(button, *position)

        self.move(0, 0)
        self.setWindowTitle('Моя читалка')
        self.show()

In the initUI() function, I create a grid with buttons, the button text is taken from the array (the text of the news list is stored in the array), there is no problem here. Also, a tooltip with a link to this news item is added to each button.
3vTYWBL.png
Next, I have written a function that, when the button is clicked, opens QMessageBox (), respectively, with the text of this news:
def initNew(self, args):
        #sender = self.sender()
        msgBox = QMessageBox()
        #url = sender.text()
        url = args
        print (url)
        g = Grab()
        g.go(url)
        msg = g.doc.select('//div[@class="post-content"]').text()
        msgBox.setText(msg)
        msgBox.setWindowTitle('Новость')
        msgBox.setStandardButtons(QMessageBox.Ok)
        ret = msgBox.exec_();

This is where the problems begin. Because in order to find the text of the news, I need a link to this news, I cannot pass a link to this news to the initNew() function. The question is how to send this link?
Unfortunately my knowledge is not enough to figure it out.
I tried the option when I displayed a link to the news in the text of the buttons:
button = QPushButton(ahref, self)
And in the parser function I took the value of the button by sender () (seen in the comment), then everything works. But the idea is to have the text on the button.
Tell me where to dig and what to try!
Thank you!
UPD:
Getting arrays via Grab:
url = 'http://slon.ru/news'
g = Grab()
g.go(url)
slon_url = 'http://slon.ru'
#настройки
xpath = '//div[@class="news-col"]'
x_news = '//h6'
x_href = '//article[@class="news-line"]/a'

#массивы
names = []
a_href = []


for news in g.doc.select(xpath):
    for text in news.select(x_news):
        names.append(text.text())

for elem in g.xpath_list(x_href):
    a_href.append((slon_url + elem.get('href')))

Answer the question

In order to leave comments, you need to log in

2 answer(s)
B
bobrovskyserg, 2015-06-29
@Triapkin

from random import randint
import tkinter


class MineSweeper(object):
    def __init__(self, rows, columns, mines_density):
        self.columns, self.rows, self.minescount = columns, rows, int(mines_density * rows * columns)
        self.window = root = tkinter.Tk()
        self.table = tkinter.Frame(self.window)
        self.table.pack()
        self.btnew = tkinter.Button(self.window, text='New')
        self.btnew.pack()
        self.btnew.config(command=lambda: self.reset())
        self.squares = []
        for y in range(rows):
            self.squares.append([])
            for x in range(columns):
                button = tkinter.Button(self.table, padx=0, pady=0, width=2, height=1, bg='silver')
                button.grid(row=x, column=y, sticky='news')
                self.squares[-1].append(button)

                def clicked(ax=x, ay=y):
                    def deeper(bx, by):
                        s = self.minesaround[by][bx]
                        if self.state[by][bx] < 0:
                            self.refresh(bx, by, s)
                            if not s:
                                for i, j in self.neighbours(bx, by):
                                    deeper(i, j)

                    if self.state[ay][ax] == -1:
                        if (ax, ay) in self.mines:
                            self.refresh(ax, ay, 9)
                        else:
                            deeper(ax, ay)

                button.config(command=clicked)

                def right_clicked(widget, ax=x, ay=y):
                    s = self.state[ay][ax]
                    if s < 0:
                        self.refresh(ax, ay, -3 - s)

                button.bind('<Button-3>', right_clicked)
        print(root.winfo_screenwidth(), (root.winfo_screenheight()))
        root.geometry('{:+d}{:+d}'.format((root.winfo_screenwidth() - columns * 70 + 11) // 2,
                                          (root.winfo_screenheight() - rows * 50 + 11) // 2))
        self.state = [[-1] * self.columns for _ in range(self.rows)]
        self.reset()

    def neighbours(self, ax, ay):
        for i in range(max(ax - 1, 0), min(ax + 2, self.columns)):
            for j in range(max(ay - 1, 0), min(ay + 2, self.rows)):
                if i != ax or j != ay:
                    yield i, j

    def reset(self):
        self.mines = set()
        while len(self.mines) < self.minescount:
            self.mines.add((randint(0, self.columns - 1), randint(0, self.rows - 1)))
        self.minesaround = [[0] * self.columns for _ in range(self.rows)]
        for x, y in self.mines:
            for i, j in self.neighbours(x, y):
                self.minesaround[j][i] += 1
        for j in range(self.rows):
            for i in range(self.columns):
                self.refresh(i, j, -1)


    def refresh(self, x, y, newstate):
        button = self.squares[y][x]
        if self.state[y][x] != newstate:
            self.state[y][x] = newstate
            text, fg = (('', None), ('1', 'blue'), ('2', 'darkgreen'), ('3', 'red'),
                        ('4', 'darkblue'), ('5', 'darkred'), ('6', 'black'), ('7', 'red'),
                        ('8', 'red'), ('☠', 'red'), ('⚑', 'yellow'), ('', None))[newstate]
            bg = bg, relief = (('white', 'sunken'), ('silver', 'raised'))[newstate < 0]
            button.config(text=text, fg=fg, bg=bg, relief=relief)


MineSweeper(40, 25, 1 / 6).window.mainloop()

S
Sergey Tryapkin, 2015-06-30
@Triapkin

Thank you!
The problem was solved like this:

def initUI(self):
        #кнопки
        grid = QGridLayout()
        self.setLayout(grid)

        positions = [(i,j) for i in range(15) for j in range(1)]

        for position, name, ahref in zip(positions, names, a_href):
            button = QPushButton(name, self)
            #button.url = ahref
            #print(open_url)
            #print(open_url)
            button.setToolTip(ahref)
            button.clicked.connect(partial(self.initNew, ahref))
            grid.addWidget(button, *position)
            #button.clicked.connect(lambda: self.initNew(button.url))
        self.move(0, 0)
        self.setWindowTitle('Моя читалка')
        self.show()

    def initNew(self, args):
        msgBox = QMessageBox()
        #url = (lambda:self.open_url)
        url = args
        print (url)
        g = Grab()
        g.go(url)
        msg = g.doc.select('//div[@class="post-content"]').text()
        msgBox.setText(msg)
        msgBox.setWindowTitle('Новость')
        msgBox.setStandardButtons(QMessageBox.Ok)
        ret = msgBox.exec_();

And about a miracle! Everything worked! :)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question