Как добавить уникальный атрибут к кнопке PyQT?

Добрый день!
После довольно долгой попытки написать свой парсер для новостных сайтов, у меня появилась идея обернуть все это в оболочку, и тут сразу появились проблемы. Суть вопроса такова, есть вот такой код:
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()

В функции initUI() у меня создается сетка с кнопками, текст кнопки берется из массива (в массиве хранится текст список новостей), тут проблема нет. Так же к каждой кнопке добавляется tooltip с ссылкой на данную новость.
3vTYWBL.png
Дальше у меня написана функция, которая при нажатие на кнопку открывает QMessageBox() соответственно с текстом данной новости:
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_();

Вот тут начинаются проблемы. Т.к. для того чтобы найти текст новости, мне требуется ссылка на эту новость, я не могу в функцию initNew() передать ссылку на эту новость. Вопрос, как передавать эту ссылку?
К сожалению моих знаний не хватает додумать это.
Был попробован вариант, когда в тексте кнопок я выводил ссылку на новость:
button = QPushButton(ahref, self)
А в функции парсера брал значение кнопки по sender() (видно в комментарии), тогда все работает. Но идея заключается в том, чтобы на кнопке был именно текст.
Подскажите куда копать и что пробовать!
Спасибо!

UPD:
Получение массивов через 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')))
  • Вопрос задан
  • 776 просмотров
Решения вопроса 1
bobrovskyserg
@bobrovskyserg
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()
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@Triapkin Автор вопроса
Спасибо!
Проблема решилась вот так:
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_();


И о чудо! Все заработало! :)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы